我有一张包含卖单的表格,我想在两个日期之间列出每天卖出订单的COUNT
,而不会留下日期空白。
这就是我目前的情况:
SELECT COUNT(*) as Norders, DATE_FORMAT(date, "%M %e") as sdate
FROM ORDERS
WHERE date <= NOW()
AND date >= NOW() - INTERVAL 1 MONTH
GROUP BY DAY(date)
ORDER BY date ASC;
我得到的结果如下:
6 May 1
14 May 4
1 May 5
8 Jun 2
5 Jun 15
但我想得到的是:
6 May 1
0 May 2
0 May 3
14 May 4
1 May 5
0 May 6
0 May 7
0 May 8
.....
0 Jun 1
8 Jun 2
.....
5 Jun 15
这可能吗?
答案 0 :(得分:3)
动态创建一系列日期并加入针对您的订单表: -
SELECT sub1.sdate, COUNT(ORDERS.id) as Norders
FROM
(
SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL units.i + tens.i * 10 + hundreds.i * 100 DAY), "%M %e") as sdate
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)tens
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)hundreds
WHERE DATE_SUB(NOW(), INTERVAL units.i + tens.i * 10 + hundreds.i * 100 DAY) BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
) sub1
LEFT OUTER JOIN ORDERS
ON sub1.sdate = DATE_FORMAT(ORDERS.date, "%M %e")
GROUP BY sub1.sdate
这可以应对最多1000天的日期范围。
请注意,根据您日期使用的字段类型,可以更轻松地提高效率。
编辑 - 根据要求,获取每月订单数量: -
SELECT aMonth, COUNT(ORDERS.id) as Norders
FROM
(
SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL months.i MONTH), "%Y%m") as sdate, DATE_FORMAT(DATE_SUB(NOW(), INTERVAL months.i MONTH), "%M") as aMonth
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11)months
WHERE DATE_SUB(NOW(), INTERVAL months.i MONTH) BETWEEN DATE_SUB(NOW(), INTERVAL 12 MONTH) AND NOW()
) sub1
LEFT OUTER JOIN ORDERS
ON sub1.sdate = DATE_FORMAT(ORDERS.date, "%Y%m")
GROUP BY aMonth
答案 1 :(得分:3)
您将需要生成一个虚拟(或物理)表,其中包含范围中的每个日期。
可以使用序列表完成以下操作。
SELECT mintime + INTERVAL seq.seq DAY AS orderdate
FROM (
SELECT CURDATE() - INTERVAL 1 MONTH AS mintime,
CURDATE() AS maxtime
FROM obs
) AS minmax
JOIN seq_0_to_999999 AS seq ON seq.seq < TIMESTAMPDIFF(DAY,mintime,maxtime)
然后,将此虚拟表加入到查询中,如下所示。
SELECT IFNULL(orders.Norders,0) AS Norders, /* show zero instead of null*/
DATE_FORMAT(alldates.orderdate, "%M %e") as sdate
FROM (
SELECT mintime + INTERVAL seq.seq DAY AS orderdate
FROM (
SELECT CURDATE() - INTERVAL 1 MONTH AS mintime,
CURDATE() AS maxtime
FROM obs
) AS minmax
JOIN seq_0_to_999999 AS seq
ON seq.seq < TIMESTAMPDIFF(DAY,mintime,maxtime)
) AS alldates
LEFT JOIN (
SELECT COUNT(*) as Norders, DATE(date) AS orderdate
FROM ORDERS
WHERE date <= NOW()
AND date >= NOW() - INTERVAL 1 MONTH
GROUP BY DAY(date)
) AS orders ON alldates.orderdate = orders.orderdate
ORDER BY alldates.orderdate ASC
请注意,您需要LEFT JOIN
,因此即使您的ORDERS
表中没有数据,输出结果集中的行也会被保留。
你在哪里得到这个序列表seq_0_to_999999
?你可以这样做。
DROP TABLE IF EXISTS seq_0_to_9;
CREATE TABLE seq_0_to_9 AS
SELECT 0 AS seq UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9;
DROP VIEW IF EXISTS seq_0_to_999;
CREATE VIEW seq_0_to_999 AS (
SELECT (a.seq + 10 * (b.seq + 10 * c.seq)) AS seq
FROM seq_0_to_9 a
JOIN seq_0_to_9 b
JOIN seq_0_to_9 c
);
DROP VIEW IF EXISTS seq_0_to_999999;
CREATE VIEW seq_0_to_999999 AS (
SELECT (a.seq + (1000 * b.seq)) AS seq
FROM seq_0_to_999 a
JOIN seq_0_to_999 b
);
您可以在http://www.plumislandmedia.net/mysql/filling-missing-data-sequences-cardinal-integers/
更详细地找到有关所有这些内容的说明如果您正在使用MariaDB版本10+,则会内置这些序列表。
答案 2 :(得分:1)
首先创建一个Calendar Table
SELECT coalesce(COUNT(O.*),0) as Norders, DATE_FORMAT(C.date, "%M %e") as sdate
FROM Calendar C
LEFT JOIN ORDERS O ON C.date=O.date
WHERE O.date <= NOW() AND O.date >= NOW() - INTERVAL 1 MONTH
GROUP BY DAY(date)
ORDER BY date ASC;