如何按 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
好吧,这可能很简单,但我似乎找不到任何解决方案
我有这个工作查询
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