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

如何在MySQL中按日期范围分组,而不跳过包含零项的日期,mysql,group-by,date-range,Mysql,Group By,Date Range,嗯,这可能很容易,但我似乎找不到任何解决办法 我有一个工作问题 SELECT count(*), TIMESTAMPDIFF(DAY, buydate, NOW()) daydif FROM order_item WHERE buydate > NOW() - INTERVAL 4 DAY GROUP BY daydif ORDER BY daydif ASC 但结果是跳过了零项的日子 +----------+--------+ | count(*) | day

嗯,这可能很容易,但我似乎找不到任何解决办法

我有一个工作问题

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      |
+----------+--------+
更新:

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

可能您没有任何物品,差异为2天。SQL无法创建某些东西,因为它不存在

您可以做的是使一个表具有一个由从0到最大的数字列表组成的长字段(在本例中为4),我们称之为tbl_diff,该字段为diff。在现有查询上左键连接tbl_diff以填补空白。请注意,我还将count()更改为仅对设置了buydate的记录进行计数

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

正如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

您可以创建一个日历表,并使用日期将其与您的
order\u项目
表左键联接。您将了解如何创建日历表。在这种情况下,不需要日历表,只要有5个数字就足够了。在这种情况下,我同意。@PaulSpiegel,哇,这真是太聪明了!在较短范围内动态创建该表不是更好的选择吗?顺便说一句:如果您使用MariaDB,您可能想看看。刚刚测试过
选择seq as daydif从seq_0_到步骤_5_1
-效果很好。
buydate>NOW()-间隔4天
应该在ON子句(IMHO)中@PaulSpiegel我不确定这是否会有任何区别。实际上,对于联接条件,它是一种冗余,因为如果差值大于4天,则联接将删除记录。如果daydif为2,则将选中
NULL>NOW()-INTERVAL 4 DAY
,然后过滤掉该行。这就是行动计划的问题。《明镜周刊》你说得对。然而,我完全改变了where子句。在第二种情况下,甚至不需要where子句。
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