我工作的公司有一个消息传递系统,我需要按照过去12个月按月合并的模板计算发送的消息,如下例所示。如果模板在指定的月份没有消息,则它应该显示为零(换句话说,如果我有2个模板,结果将是24行,每个模板12个月):
-----------------------------
| date | template | qqty |
-----------------------------
| 01/2015 | tpl1 | 100 |
-----------------------------
| 01/2015 | tpl2 | 10 |
-----------------------------
| 02/2015 | tpl1 | 90 |
-----------------------------
| 02/2015 | tpl2 | 0 |
-----------------------------
我正在努力实现在this和this帖子中提出/提交的结果。我们使用SQLSERVER而不是MySQL。
基本上系统有两个表:
MESSAGE
---------------------------------
| msg_id | tpl_id | date |
---------------------------------
| 1 | 1 | 03/01/2015 |
---------------------------------
| 2 | 1 | 15/01/2015 |
---------------------------------
| 3 | 2 | 04/01/2015 |
---------------------------------
| 4 | 1 | 22/02/2015 |
---------------------------------
TEMPLATE
---------------------
| tpl_id | tpl_name |
---------------------
| 1 | tpl1 |
---------------------
| 2 | tpl2 |
---------------------
我做了以下SQL。它一直有效,直到我启用模板连接。如果我启用它,结果将只显示系统记录的月份......
SELECT
years.y, months.m, --tpl.tpl_name,
COUNT(msg.msg_id) AS Total
FROM (
SELECT year(getdate()) AS y UNION ALL
SELECT year(getdate()) - 1 AS y
) years
CROSS JOIN (
SELECT 1 AS m UNION ALL
SELECT 2 AS m UNION ALL
SELECT 3 AS m UNION ALL
SELECT 4 AS m UNION ALL
SELECT 5 AS m UNION ALL
SELECT 6 AS m UNION ALL
SELECT 7 AS m UNION ALL
SELECT 8 AS m UNION ALL
SELECT 9 AS m UNION ALL
SELECT 10 AS m UNION ALL
SELECT 11 AS m UNION ALL
SELECT 12 AS m
) months
LEFT JOIN MESSAGE msg ON YEAR(msg.date) = years.y AND MONTH(msg.date) = months.m
--LEFT JOIN TEMPLATE tpl ON tpl.tpl_id = msg.tpl_id
WHERE
(CONVERT(DATETIME, CONVERT(VARCHAR(4), YEAR(GETDATE())) + '-' + CONVERT(VARCHAR(2), MONTH(GETDATE())) + '-01')) >= DATEADD(month, -12, GETDATE())
AND (CONVERT(DATETIME, CONVERT(VARCHAR(4), YEAR(GETDATE())) + '-' + CONVERT(VARCHAR(2), MONTH(GETDATE())) + '-01')) <= GETDATE()
GROUP BY years.y, months.m--, tpl.tpl_name
ORDER BY years.y, months.m--, tpl.tpl_name
我的SQL知识是基本的。我试图将连接更改为RIGHT,OUTER等,但没有成功。
拜托,您能帮我指出如何实现它吗?
答案 0 :(得分:1)
首先交叉连接TEMPLATE然后离开加入消息。
FROM (...
) years
CROSS JOIN (...
) months
CROSS JOIN TEMPLATE tpl
LEFT JOIN MESSAGE msg ON YEAR(msg.date) = years.y
AND MONTH(msg.date) = months.m AND tpl.tpl_id = msg.tpl_id
答案 1 :(得分:1)
从概念上讲,您需要构建要报告的项目列表(年x月x模板),然后(通过外部联接)处理列表中每个项目的数据。在这里,我将TEMPLATE上的连接更改为交叉连接:
SELECT
years.y, months.m, tpl.tpl_name,
COUNT(msg.msg_id) AS Total
FROM (
SELECT year(getdate()) AS y
UNION ALL SELECT year(getdate()) - 1 AS y
) years
CROSS JOIN (
SELECT 1 AS m UNION ALL
SELECT 2 AS m UNION ALL
SELECT 3 AS m UNION ALL
SELECT 4 AS m UNION ALL
SELECT 5 AS m UNION ALL
SELECT 6 AS m UNION ALL
SELECT 7 AS m UNION ALL
SELECT 8 AS m UNION ALL
SELECT 9 AS m UNION ALL
SELECT 10 AS m UNION ALL
SELECT 11 AS m UNION ALL
SELECT 12 AS m
) months
CROSS JOIN TEMPLATE tpl -- Assumes there are just the two templates in the table
LEFT JOIN MESSAGE msg
ON YEAR(msg.date) = years.y
AND MONTH(msg.date) = months.m
AND msg.tpl_id = tpl.tpl_id
WHERE
(CONVERT(DATETIME, CONVERT(VARCHAR(4), YEAR(GETDATE())) + '-' + CONVERT(VARCHAR(2), MONTH(GETDATE())) + '-01')) >= DATEADD(month, -12, GETDATE())
AND (CONVERT(DATETIME, CONVERT(VARCHAR(4), YEAR(GETDATE())) + '-' + CONVERT(VARCHAR(2), MONTH(GETDATE())) + '-01')) <= GETDATE()
GROUP BY years.y, months.m--, tpl.tpl_name
ORDER BY years.y, months.m--, tpl.tpl_name
(我无法测试查询,但应该很好。)