MySQL:获得累积计数和差异计数的任何好方法?

时间:2017-12-06 08:52:32

标签: mysql sql

假设我有以下数据集。

+--------------------+
| item_id count date |
+--------------------+
| 000 10 2017-11-01  |
| 001 15 2017-11-01  |
| 002 2 2017-11-01   |
| 003 100 2017-11-01 |
| 000 20 2017-11-02  |
| 001 20 2017-11-02  |
| 002 22 2017-11-02  |
| 003 101 2017-11-02 |
| 000 30 2017-11-03  |
| 001 25 2017-11-03  |
| 002 42 2017-11-03  |
| 003 102 2017-11-03 |
| 000 40 2017-11-04  |
| 001 30 2017-11-04  |
| 002 62 2017-11-04  |
| 003 103 2017-11-04 |
+--------------------+

有没有办法在两个任意日期之间获得每天的累积计数和差异计数? (至于差异计数,如果选择的日期是2017-11-01和2017-11-04,则第一个差异计数(2017-11-01)不必包含在最终的SQL结果中,因为没有在该日期之前可获得的数据)

以下两个表是预期的SQL结果。

累积计数

+--------------------+
| item_id count date |
+--------------------+
| 000 10 2017-11-01  |
| 000 30 2017-11-02  |
| 000 60 2017-11-03  |
| 000 100 2017-11-03 |
| 001 15 2017-11-01  |
| 001 35 2017-11-02  |
| 001 60 2017-11-03  |
| 001 90 2017-11-04  |
| 002 2 2017-11-01   |
| 002 24 2017-11-02  |
| 002 66 2017-11-03  |
| 002 128 2017-11-04 |
| 003 100 2017-11-01 |
| 003 201 2017-11-02 |
| 003 303 2017-11-03 |
| 003 406 2017-11-04 |
+--------------------+

差异计数

+--------------------+
| item_id count date |
+--------------------+
| 000 10 2017-11-02  |
| 000 10 2017-11-03  |
| 000 10 2017-11-04  |
| 001 5 2017-11-02   |
| 001 5 2017-11-03   |
| 001 5 2017-11-04   |
| 002 20 2017-11-02  |
| 002 20 2017-11-03  |
| 002 20 2017-11-04  |
| 003 1 2017-11-02   |
| 003 1 2017-11-03   |
| 003 1 2017-11-04   |
+--------------------+

2 个答案:

答案 0 :(得分:2)

由于a不支持Windows MySQL函数(最新版本除外),因此可以使用变量。

累积SUM:

OLAP

结果:

set @item_id := 0;
set @val := 0;

select t.item_id, t.count, t.date, t.CSUM as CummulativeSUM
from (
select t1.*, 
       @val := if(@item_id=item_id, @val + t1.count, t1.count) as CSUM,
       @item_id := item_id
from table1 t1
order by t1.item_id, t1.date
    ) t;

<强> Cumulative SUM DEMO

DIFF计数:

+---------+-------+---------------------+----------------+
| item_id | count |        date         | CummulativeSUM |
+---------+-------+---------------------+----------------+
|       0 |    10 | 01.11.2017 00:00:00 |             10 |
|       0 |    20 | 02.11.2017 00:00:00 |             30 |
|       0 |    30 | 03.11.2017 00:00:00 |             60 |
|       0 |    40 | 04.11.2017 00:00:00 |            100 |
|       1 |    15 | 01.11.2017 00:00:00 |             15 |
|       1 |    20 | 02.11.2017 00:00:00 |             35 |
|       1 |    25 | 03.11.2017 00:00:00 |             60 |
|       1 |    30 | 04.11.2017 00:00:00 |             90 |
|       2 |     2 | 01.11.2017 00:00:00 |              2 |
|       2 |    22 | 02.11.2017 00:00:00 |             24 |
|       2 |    42 | 03.11.2017 00:00:00 |             66 |
|       2 |    62 | 04.11.2017 00:00:00 |            128 |
|       3 |   100 | 01.11.2017 00:00:00 |            100 |
|       3 |   101 | 02.11.2017 00:00:00 |            201 |
|       3 |   102 | 03.11.2017 00:00:00 |            303 |
|       3 |   103 | 04.11.2017 00:00:00 |            406 |
+---------+-------+---------------------+----------------+

结果:

set @item_id1 := 0;
set @val1 := 0; 
set @count := 0;

select t.item_id, t.count, t.date, t.CSUM as diffSUM
from (
select t1.*, 
       @val1 := if(@item_id1=item_id, t1.count - @count, t1.count) as CSUM,
       @item_id1 := item_id,
       @count := count
from table1 t1
order by t1.item_id, t1.date
    ) t
where count <> csum;

<强> DIFF Count DEMO

答案 1 :(得分:1)

看看这个,看看它是否有用。这是ms sql server方法,但希望有足够的帮助。

DECLARE @Tbl AS TABLE (item CHAR(3)
                      ,count INT
                      ,date DATE
                      )
INSERT  INTO @Tbl
        (item, count, date)
VALUES  ('000', 10, '2017-11-01'),
        ('001', 15, '2017-11-01'),
        ('002', 2, '2017-11-01'),
        ('003', 100, '2017-11-01'),
        ('000', 20, '2017-11-02'),
        ('001', 20, '2017-11-02'),
        ('002', 22, '2017-11-02'),
        ('003', 101, '2017-11-02'),
        ('000', 30, '2017-11-03'),
        ('001', 25, '2017-11-03'),
        ('002', 42, '2017-11-03'),
        ('003', 102, '2017-11-03'),
        ('000', 40, '2017-11-04'),
        ('001', 30, '2017-11-04'),
        ('002', 62, '2017-11-04'),
        ('003', 103, '2017-11-04');
WITH    cte
          AS (SELECT    *
              ,         ROW_NUMBER() OVER (PARTITION BY item ORDER BY date) RN
              FROM      @Tbl
             )
    SELECT  A.item
     ,      A.count
     ,      A.date
     ,      C.Cume
    FROM    cte A
    CROSS APPLY (SELECT SUM(count) Cume
                 FROM   cte B
                 WHERE  A.item = B.item
                        AND A.RN >= B.RN
                ) C

这是如何针对您的数据获取cume总计的一般示例。添加日期范围应该足够简单。使用行号技术,您可以将之前的总和替换为与之前的差值。

如果您在查看完之后仍然卡住了,那么请告诉我,我也可以编写代码,但如果您能理解这里已经完成的并运用您自己的解决方案,那就更好了。