如何按 MySQL 中的日期范围分组而不跳过零项的日期

how to group by a date range in MySQL and not skip dates with zero items

好吧,这可能很简单,但我似乎找不到任何解决方案

我有这个工作查询

SELECT 
    count(*), TIMESTAMPDIFF(DAY, buydate, NOW()) daydif
FROM
    order_item
WHERE
    buydate > NOW() - INTERVAL 4 DAY
GROUP BY daydif
ORDER BY daydif ASC

但结果是跳过了零项的日子

+----------+--------+
| count(*) | daydif |
+==========+========+
| 5        | 0      |
+----------+--------+
| 9        | 1      |
+----------+--------+
| 2        | 3      |
+----------+--------+

我想得到这个结果

+----------+--------+
| count(*) | daydif |
+==========+========+
| 5        | 0      |
+----------+--------+
| 9        | 1      |
+----------+--------+
| 0        | 2      |  //I want this row in the returned results
+----------+--------+
| 2        | 3      |
+----------+--------+

更新:
从答案和进一步搜索来看,我似乎被迫创建一个助手 table 并加入它。令人沮丧的是,我找不到像评论中提到的 MariaDB 那样的序列生成函数。任何更优雅的方式提示?

可能您没有任何物品,相差 2 天。 SQL 无法创建某物,那是不存在的。

你可以做的是让一个 table 有一个长长的数字列表字段,从 0 到最大的差异(在本例中为 4),我们称它为 tbl_diff,字段是diff。在您现有的查询上左加入 tbl_diff 以填补空白。请注意,我还更改了 count() 以仅计算那些设置了购买日期的记录。

SELECT 
    count(buydate), TIMESTAMPDIFF(DAY, buydate, NOW()) daydif
FROM
    tbl_diff
LEFT JOIN
    order_item on tbl_diff.diff=TIMESTAMPDIFF(DAY, buydate, NOW())
WHERE
    diff<=4
GROUP BY daydif
ORDER BY daydif ASC

如果你不想创建一个helpertable,那么你可以使用一系列联合操作,因为你只需要5个数字(0到4):

SELECT 
    count(buydate), TIMESTAMPDIFF(DAY, buydate, NOW()) daydif
FROM
    (SELECT 0 as diff FROM dual
     UNION
     SELECT 1 FROM dual
     UNION
     SELECT 2 FROM dual
     UNION
     SELECT 3 FROM dual
     UNION
     SELECT 4 FROM dual) tbl_diff
LEFT JOIN
    order_item on tbl_diff.diff=TIMESTAMPDIFF(DAY, buydate, NOW())
GROUP BY daydif
ORDER BY daydif ASC

根据 Paul Spiegel 的建议,我最终使用了一些帮助表, 为了将来参考和更好的帮助,这是我用来生成表格的代码

create table `stat_helper_calendar` (
  `date` DATE NOT NULL,
  PRIMARY KEY (`date`)
)
  select date_add('2015-01-01', INTERVAL  t3.c*1000 + t2.c*100 + t1.c*10 + t0.c DAY) as `date`
  from
    (select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t0,
    (select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t1,
    (select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t2,
    (select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t3

这个是整数

CREATE TABLE `stat_helper_num` (
  `num` INT NOT NULL,
  PRIMARY KEY (`num`)
) SELECT (t4.c * 10000 + t3.c * 1000 + t2.c * 100 + t1.c * 10 + t0.c) AS `num` FROM
  (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t0,
  (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
  (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
  (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,
  (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4