我正在尝试获取过去 12 个月的预订日期计数,但对于没有预订的月份,我需要获取 Null 或 0。下面的查询会跳过没有预订的月份,
SELECT bs.date,CONCAT(MONTHNAME(bs.date),' ', YEAR(bs.date)) as 'Month',count(*) AS Bookings, CONCAT(us.firstName,' ', us.lastName) as 'Name' from bookings bs RIGHT JOIN users us ON bs.clientID = us.recNo
WHERE bs.managerID = 6 AND bs.clientID = 1900
AND date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND date <= CURDATE() GROUP BY YEAR(date), month(date)
有人可以帮忙吗?
最佳答案
您可以通过硬编码其中的 12 个月并与 users
进行 CROSS JOIN,然后与 bookings
进行 LEFT JOIN(我听其他人提到 LEFT JOIN 更快)比右连接)。
所以查询如下
SELECT bs.date,
CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month',
count(bs.date) AS Bookings,
CONCAT(us.firstName,' ', us.lastName) as 'Name'
from
(SELECT CURDATE() as date UNION
SELECT CURDATE()-INTERVAL 1 MONTH UNION
SELECT CURDATE()-INTERVAL 2 MONTH UNION
SELECT CURDATE()-INTERVAL 3 MONTH UNION
SELECT CURDATE()-INTERVAL 4 MONTH UNION
SELECT CURDATE()-INTERVAL 5 MONTH UNION
SELECT CURDATE()-INTERVAL 6 MONTH UNION
SELECT CURDATE()-INTERVAL 7 MONTH UNION
SELECT CURDATE()-INTERVAL 8 MONTH UNION
SELECT CURDATE()-INTERVAL 9 MONTH UNION
SELECT CURDATE()-INTERVAL 10 MONTH UNION
SELECT CURDATE()-INTERVAL 11 MONTH
)as hardcoded
CROSS JOIN users us
LEFT JOIN bookings bs ON (MONTH(bs.date) = MONTH(hardcoded.date)
AND YEAR(bs.date) = YEAR(hardcoded.date))
AND bs.clientID = us.recNo
WHERE ((bs.managerID = 6 AND bs.clientID = 1900)
OR
(bs.managerID IS NULL AND bs.clientID IS NULL))
AND hardcoded.date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND hardcoded.date <= CURDATE()
GROUP BY Month,Name
ORDER BY hardcoded.date
请参阅 ( sqlFiddle )
注意:因为有一个 WHERE 条件来检查 managerID 和 clientID 以过滤出我们想要的结果,但我们也希望返回具有空值的行,这意味着我们的硬编码月份没有预订。这就是为什么有 OR (bs.managerID IS NULL AND bs.clientID IS NULL)
此外,当前的 GROUP BY 是非标准的,因为它没有对选择 bs.date
的第一个字段进行分组,因此现在如果您在一个月内有 2 个或更多预订,它只会返回一个日期,而不是知道哪一个看起来很奇怪,您可能需要选择 hardcoded.date
并对其进行 GROUP BY,这样您就有一个 ANSI 标准正确的 GROUP BY。或者更好的是,对选择中的第一个字段使用 MIN() 或 MAX() 到 MIN(bs.date) 或 MAX(bs.date) 之类的聚合函数,以确保它始终返回第一个预订日期或最后一个预订日期每月的日期(如果该月有 2 个或更多预订),这样您就不会将其列在 GROUP BY 中。
我不知道 CROSS JOIN 是否会杀死您的应用程序,但您可以尝试这个 它没有 CROSS JOIN,但保留了您的 RIGHT JOIN
SELECT bs.date,
CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month',
count(bs.date) AS Bookings,
CONCAT(us.firstName,' ', us.lastName) as 'Name'
from
(SELECT CURDATE() as date UNION
SELECT CURDATE()-INTERVAL 1 MONTH UNION
SELECT CURDATE()-INTERVAL 2 MONTH UNION
SELECT CURDATE()-INTERVAL 3 MONTH UNION
SELECT CURDATE()-INTERVAL 4 MONTH UNION
SELECT CURDATE()-INTERVAL 5 MONTH UNION
SELECT CURDATE()-INTERVAL 6 MONTH UNION
SELECT CURDATE()-INTERVAL 7 MONTH UNION
SELECT CURDATE()-INTERVAL 8 MONTH UNION
SELECT CURDATE()-INTERVAL 9 MONTH UNION
SELECT CURDATE()-INTERVAL 10 MONTH UNION
SELECT CURDATE()-INTERVAL 11 MONTH
)as hardcoded
LEFT JOIN bookings bs ON (MONTH(bs.date) = MONTH(hardcoded.date)
AND YEAR(bs.date) = YEAR(hardcoded.date))
RIGHT JOIN users us ON (bs.clientID = us.recNo OR bs.clientID IS NULL)
WHERE ((bs.managerID = 6 AND bs.clientID = 1900)
OR
(bs.managerID IS NULL AND bs.clientID IS NULL))
AND hardcoded.date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND hardcoded.date <= CURDATE()
GROUP BY Month,Name
ORDER BY hardcoded.date
在加入之前尝试缩小记录范围
SELECT MIN(bs.date) as FirstBookingDate,
CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month',
count(bs.date) AS Bookings,
CONCAT(us.firstName,' ', us.lastName) as 'Name'
from
(SELECT CURDATE() as date UNION
SELECT CURDATE()-INTERVAL 1 MONTH UNION
SELECT CURDATE()-INTERVAL 2 MONTH UNION
SELECT CURDATE()-INTERVAL 3 MONTH UNION
SELECT CURDATE()-INTERVAL 4 MONTH UNION
SELECT CURDATE()-INTERVAL 5 MONTH UNION
SELECT CURDATE()-INTERVAL 6 MONTH UNION
SELECT CURDATE()-INTERVAL 7 MONTH UNION
SELECT CURDATE()-INTERVAL 8 MONTH UNION
SELECT CURDATE()-INTERVAL 9 MONTH UNION
SELECT CURDATE()-INTERVAL 10 MONTH UNION
SELECT CURDATE()-INTERVAL 11 MONTH
)as hardcoded
CROSS JOIN (SELECT * FROM users WHERE recNo = 1900) us
LEFT JOIN (SELECT * FROM bookings WHERE managerID = 6 AND clientID = 1900
AND date BETWEEN CURDATE()-INTERVAL 11 MONTH AND CURDATE()) bs
ON (MONTH(bs.date) = MONTH(hardcoded.date)
AND YEAR(bs.date) = YEAR(hardcoded.date))
GROUP BY Month,Name
ORDER BY hardcoded.date
关于MySQL 查询 - 返回每个月过去 12 个月记录的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21081741/