2014-10-28 122 views
0

我想弄清楚如何通过MySQL进行一些流量统计,我可以分成计费月份。计算流量统计的计费周期

我有一个表(traffic_logs)有:

日期| ip |入站|出站| last_updated

这会得到填充/更新以提供日常计数。

我有,有一个服务表:

SERVICE_NAME |过期| IPADDR

我目前使用的查询,如:

SELECT SUM(inbound) AS traffic_in, SUM(outbound) AS traffic_out 
FROM services 
JOIN traffic_logs ON services.ip = traffic_logs.ip 
GROUP BY ip 
ORDER BY service_name; 

当我陷入的是,我想找到当前的结算月份的流量。

实施例的数据集:

 
traffic_logs table: 
+---------------+------------+------------+------------+---------------------+ 
|  ip  | date | inbound | outbound | last_updated  | 
+---------------+------------+------------+------------+---------------------+ 
| 192.168.1.100 | 2014-10-08 | 40372536 | 454591053 | 2014-10-08 23:55:03 | 
| 192.168.1.100 | 2014-10-09 | 22275659 | 241704264 | 2014-10-09 23:55:03 | 
| 192.168.1.100 | 2014-10-10 | 23481329 | 350904975 | 2014-10-10 23:55:03 | 
| 192.168.1.100 | 2014-10-11 | 28148019 | 177964416 | 2014-10-11 23:55:04 | 
| 192.168.1.100 | 2014-10-12 | 46099322 | 1383179073 | 2014-10-12 23:55:05 | 
| 192.168.1.100 | 2014-10-13 | 30171788 | 177338415 | 2014-10-13 23:55:06 | 
| 192.168.1.100 | 2014-10-14 | 22821090 | 260455364 | 2014-10-14 23:55:07 | 
| 192.168.1.100 | 2014-10-15 | 30049347 | 206231505 | 2014-10-15 23:55:07 | 
| 192.168.1.100 | 2014-10-16 | 33703952 | 413556561 | 2014-10-16 23:55:09 | 
| 192.168.1.100 | 2014-10-17 | 32386602 | 533711743 | 2014-10-17 23:55:10 | 
| 192.168.1.100 | 2014-10-18 | 34650714 | 576704272 | 2014-10-18 23:55:10 | 
| 192.168.1.100 | 2014-10-19 | 41040926 | 636292627 | 2014-10-19 23:55:10 | 
| 192.168.1.100 | 2014-10-20 | 40022284 | 542582298 | 2014-10-20 23:55:12 | 
| 192.168.1.100 | 2014-10-21 | 98535882 | 336734189 | 2014-10-21 23:55:12 | 
| 192.168.1.100 | 2014-10-22 | 41569882 | 292757699 | 2014-10-22 23:55:13 | 
| 192.168.1.100 | 2014-10-23 | 2147483647 | 934724220 | 2014-10-23 23:55:01 | 
| 192.168.1.100 | 2014-10-24 | 2147483647 | 462654543 | 2014-10-24 23:55:01 | 
| 192.168.1.100 | 2014-10-25 | 312027896 | 321416702 | 2014-10-25 23:55:01 | 
| 192.168.1.100 | 2014-10-26 | 34953533 | 341663241 | 2014-10-26 23:55:03 | 
| 192.168.1.100 | 2014-10-27 | 34335294 | 236423425 | 2014-10-27 23:55:03 | 
| 192.168.1.100 | 2014-10-28 | 34919816 | 492949009 | 2014-10-28 16:00:03 | 
+---------------+------------+------------+------------+---------------------+ 
 
services table: 
+---------------+------------+---------------+ 
| service_name | expires |  ip  | 
+---------------+------------+---------------+ 
| my_web_server | 2014-11-29 | 192.168.1.100 | 
| my_ftp_server | 2014-11-15 | 192.168.1.101 | 
+---------------+------------+---------------+ 

当服务被更新,它被更新为expires=DATE_ADD(expires, INTERVAL 1 MONTH)

现在我正在尝试计算当月结算周期内使用的流量。对于以上两个例子的计费周期将是:

 
my_web_server: 
    2014-10-30 -> 2014-11-29 
    2014-09-30 -> 2014-10-29 
    2014-08-30 -> 2014-09-29 

my_ftp_server: 
    2014-10-16 -> 2014-11-15 
    2014-09-16 -> 2014-10-15 
    2014-08-16 -> 2014-09-15 

当我得到WHERE date BETWEEN(DATE_ADD(DATE_SUB(expires, INTERVAL 1 MONTH), INTERVAL 1 DAY) AND NOW()交通是一个月的时间内,一切都很好。

产品在到期前已被更新时会出现问题。这意味着expires大于INTERVAL 1 MONTHNOW()

例如:如果my_ftp_server在2014年11月10日更新,则expires将变为2014-12-10 - 这将使WHERE date BETWEEN(DATE_ADD(DATE_SUB(expires, INTERVAL 1 MONTH), INTERVAL 1 DAY) AND NOW()的WHERE子句返回2014-11-16至2014-12年的日期 - 15 - 这实际上是下一个计费月份。

因此,我需要能够获得当前的结算周期。如果DATEDIFF(过期,NOW())大于INTERVAL 1 MONTH,那么可以选择流量与WHERE date > DATE_SUB(expires, INTERVAL 2 MONTH) - but if the difference between NOW() and到期is less than INTERVAL 1 MONTH, then I could use WHERE date> DATE_SUB(过期,INTERVAL 1个月) `

+0

没有足够的信息。什么是帐单月份?所有客户都一样吗?这听起来像你的系统设计不完整。您必须更好地定义结算月的构成,如果是每个客户,那么您需要在'services'表中定义与当前到期日截然不同的月份边界中的另一列。注意边界条件。如果月份边界是31号,那么月份会有几天发生什么呢? – 2014-10-28 00:24:38

+0

这段时间总是一个月 - 每个产品都不相同。 expires字段始终是结算周期的最后一天。因此,DATE_SUB(到期,INTERVAL 1 MONTH)是最新的结算周期。 MySQL似乎在这方面处理日期非常好。 1月的最后一天将在2月的最后一天根据日期操作 - 它做适当的闰年等计算... 正如我所提到的 - 当NOW介于DATE_SUB(过期,INTERVAL 1月)和NOW()是事情破裂的地方。 – 2014-10-28 00:28:54

+0

@StevenHigh。 。 。您的问题可以通过样本数据和预期结果更容易理解。 – 2014-10-28 00:55:52

回答

0

您正在使用一个数据项expires来表示两个不同的信息,尽管它们大多数时间都是相同的,但CAN会有所不同。

你不能这样做,没有歧义。

您必须使用不同的字段来存储它们,一个用来表示结算周期,一个用来表示已付清的到期日期。他们在“大部分时间”都是一样的事实并不重要。它们代表完全不同的数据项。

如果到期时间总是发生在结算周期结束时,并且客户的周期不能改变,您可以通过仅存储到期月/年来节省几个字节,但我认为这不值得如果需求发生变化,将会变得更加脆弱。

为结算周期添加第二列。

+0

我听到你在说什么,但是似乎还需要更多的工作来需要一个单独的进程来计算如下内容:如果end_cycle = expires - interval 1 month,则SET end_cycle =在当前结算周期结束时过期以保持更新。 – 2014-10-28 00:58:39