我目前正在使用MySQL进行月度报告。我有一个名为“monthly”的表,看起来像这样:
id | date | amount
10 | 2009-12-01 22:10:08 | 7
9 | 2009-11-01 22:10:08 | 78
8 | 2009-10-01 23:10:08 | 5
7 | 2009-07-01 21:10:08 | 54
6 | 2009-03-01 04:10:08 | 3
5 | 2009-02-01 09:10:08 | 456
4 | 2009-02-01 14:10:08 | 4
3 | 2009-01-01 20:10:08 | 20
2 | 2009-01-01 13:10:15 | 10
1 | 2008-12-01 10:10:10 | 5
然后,当我每月报告(基于每年的每月)时,我会得到类似的结果。
2008-12 | 5
2009-01 | 30
2009-02 | 460
2009-03 | 3
2009-07 | 54
2009-10 | 5
2009-11 | 78
2009-12 | 7
我使用此查询来获得结果:
SELECT substring(date,1,7)AS yearmonth,sum(amount)AS total
来自monthly
GROUP BY substring(date,1,7)
但我需要这样的事情:
2008-01 | 0
2008-02 | 0
2008-03 | 0
2008-04 | 0
2008-05 | 0
2008-06 | 0
2008-07 | 0
2008-08 | 0
2008-09 | 0
2008-10 | 0
2008-11 | 0
2008-12 | 5
2009-01 | 30
2009-02 | 460
2009-03 | 3
2009-05 | 0
2009-06 | 0
2009-07 | 54
2009-08 | 0
2009-09 | 0
2009-10 | 5
2009-11 | 78
2009-12 | 7
显示没有任何价值的月份的零的东西。甚至可以在MySQL查询中执行此操作吗?
答案 0 :(得分:4)
你应该用它生成一个虚拟行源和LEFT JOIN
:
SELECT *
FROM (
SELECT 1 AS month
UNION ALL
SELECT 2
…
UNION ALL
SELECT 12
) months
CROSS JOIN
(
SELECT 2008 AS year
UNION ALL
SELECT 2009 AS year
) years
LEFT JOIN
mydata m
ON m.date >= CONCAT_WS('.', year, month, 1)
AND m.date < CONCAT_WS('.', year, month, 1) + INTERVAL 1 MONTH
GROUP BY
year, month
您可以在磁盘上创建这些表,而不是每次都生成它们。
MySQL
是四大系统中唯一能够轻松生成任意结果集的系统。
Oracle
,SQL Server
和PostgreSQL
分别有{CONNECT BY
,递归CTE
和generate_series
答案 1 :(得分:0)
Quassnoi是对的,我会添加一条关于如何识别你需要什么的评论:
您希望在结果中使用“2008-01”,但源表中没有任何日期在2008年1月。结果集必须来自您查询的表,因此显而易见的结论是您需要一个额外的表 - 包含您希望作为结果一部分的每个月的一个。