SQL 查询:计数,按月-年分组,具有多个日期字段
Posted
技术标签:
【中文标题】SQL 查询:计数,按月-年分组,具有多个日期字段【英文标题】:SQL Query: Count, Group By Month-Year with Multiple Date Fields 【发布时间】:2020-01-30 19:26:33 【问题描述】:我有一个如下所示的表格,其中所有列都是记录特定操作日期的日期字段。假设有 10 个这样的日期字段(仅使用我的查询/输出中的 10 个日期字段)
---------------------------------------------------------
| Date_Event1 | Date_Event2 | Date_Event3 | Date_Event4 |
---------------------------------------------------------
| NULL | NULL | 2019-03-04 | NULL |
| 2019-01-07 | 2019-03-04 | 2019-02-08 | 2019-02-15 |
| 2019-01-04 | NULL | 2019-02-10 | NULL |
| NULL | 2019-01-10 | NULL | 2019-01-11 |
| 2019-02-04 | NULL | 2019-03-04 | NULL |
| NULL | 2019-02-04 | 2019-03-20 | NULL |
| 2019-01-04 | NULL | 2019-02-13 | 2019-03-22 |
我正在尝试获取按月-年对所有列进行分组并计算每个月-年中每个 Date_Event 的出现次数的输出,类似于以下内容。
-----------------------------------------------------------------------
| Month-Year | Date_Event1 | Date_Event2 | Date_Event3 | Date_Event4 |
-----------------------------------------------------------------------
| 01-2019 | 3 | 1 | NULL | 1 |
| 02-2019 | 1 | 1 | 3 | 1 |
| 03-2019 | NULL | 1 | 3 | 1 |
真的不知道从哪里开始
【问题讨论】:
你用的是sql server吗?你能标记一下sql平台吗 抱歉,使用的是postgresql平台 【参考方案1】:这是一个对每一列进行子查询的示例。
SELECT RIGHT('0' + CAST(allDates.EventMonth AS CHAR(2)), 2) + '-' + CAST(allDates.EventYear AS CHAR(4)) AS [Month-Year],
(SELECT COUNT(1) FROM EventTable WHERE DATEPART(YEAR, Date_Event1) = allDates.EventYear AND DATEPART(MONTH, Date_Event1) = allDates.EventMonth) AS Date_Event1,
(SELECT COUNT(1) FROM EventTable WHERE DATEPART(YEAR, Date_Event2) = allDates.EventYear AND DATEPART(MONTH, Date_Event2) = allDates.EventMonth) AS Date_Event2,
(SELECT COUNT(1) FROM EventTable WHERE DATEPART(YEAR, Date_Event3) = allDates.EventYear AND DATEPART(MONTH, Date_Event3) = allDates.EventMonth) AS Date_Event3,
(SELECT COUNT(1) FROM EventTable WHERE DATEPART(YEAR, Date_Event4) = allDates.EventYear AND DATEPART(MONTH, Date_Event4) = allDates.EventMonth) AS Date_Event4
FROM (
SELECT EventYear, EventMonth
FROM (
SELECT DATEPART(YEAR, Date_Event1) AS EventYear, DATEPART(MONTH, Date_Event1) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event2) AS EventYear, DATEPART(MONTH, Date_Event2) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event3) AS EventYear, DATEPART(MONTH, Date_Event3) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event4) AS EventYear, DATEPART(MONTH, Date_Event4) AS EventMonth
FROM EventTable
) AS allDates
GROUP BY EventYear, EventMonth
) AS allDates
ORDER BY allDates.EventYear, allDates.EventMonth
此示例使用 INNER JOIN,但根据表大小、索引可能会执行得更好。等等
SELECT RIGHT('0' + CAST(allDates.EventMonth AS CHAR(2)), 2) + '-' + CAST(allDates.EventYear AS CHAR(4)) AS [Month-Year],
SUM(IIF(DATEPART(YEAR, e.Date_Event1) = allDates.EventYear AND DATEPART(MONTH, e.Date_Event1) = allDates.EventMonth, 1, 0)) AS Date_Event1,
SUM(IIF(DATEPART(YEAR, e.Date_Event2) = allDates.EventYear AND DATEPART(MONTH, e.Date_Event2) = allDates.EventMonth, 1, 0)) AS Date_Event2,
SUM(IIF(DATEPART(YEAR, e.Date_Event3) = allDates.EventYear AND DATEPART(MONTH, e.Date_Event3) = allDates.EventMonth, 1, 0)) AS Date_Event3,
SUM(IIF(DATEPART(YEAR, e.Date_Event4) = allDates.EventYear AND DATEPART(MONTH, e.Date_Event4) = allDates.EventMonth, 1, 0)) AS Date_Event4,
FROM (
SELECT EventYear, EventMonth
FROM (
SELECT DATEPART(YEAR, Date_Event1) AS EventYear, DATEPART(MONTH, Date_Event1) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event2) AS EventYear, DATEPART(MONTH, Date_Event2) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event3) AS EventYear, DATEPART(MONTH, Date_Event3) AS EventMonth
FROM EventTable
UNION ALL
SELECT DATEPART(YEAR, Date_Event4) AS EventYear, DATEPART(MONTH, Date_Event4) AS EventMonth
FROM EventTable
) AS allDates
GROUP BY EventYear, EventMonth
) AS allDates
INNER JOIN EventTable AS e ON 1 = 1
GROUP BY allDates.EventYear, allDates.EventMonth
ORDER BY allDates.EventYear, allDates.EventMonth
【讨论】:
谢谢,效果很好!对于其他可能正在看这个的人,我最终使用了带有 INNER JOIN 的那个,因为它处理了一半的时间,并用 CASE/WHEN 切换了 IIF 函数以在 Redshift 中使用。感谢您的帮助!【参考方案2】:您可以将其扩展到更多列
对于 SQL Server:
with cte as
(
select NULL as Date_Event1 , NULL as Date_Event2 , '2019-03-04' as Date_Event3, NULL as Date_Event4
union select '2019-01-07', '2019-03-04', '2019-02-08', '2019-02-15'
union select '2019-01-04', NULL , '2019-02-10', NULL
union select NULL , '2019-01-10', NULL , '2019-01-11'
union select '2019-02-04', NULL , '2019-03-04', NULL
union select NULL , '2019-02-04', '2019-03-20', NULL
union select '2019-01-04', NULL , '2019-02-13', '2019-03-22'
),
yyyydd as
(
select CONVERT(VARCHAR(7), Date_Event1, 126) as [Month-Year] from cte where Date_Event1 is not null
union select CONVERT(VARCHAR(7), Date_Event2, 126) from cte where Date_Event2 is not null
union select CONVERT(VARCHAR(7), Date_Event3, 126) from cte where Date_Event3 is not null
union select CONVERT(VARCHAR(7), Date_Event4, 126) from cte where Date_Event4 is not null
)
select [Month-Year]
, ( select sum(case when b.Date_Event1 is null then null else 1 end) from cte b where a.[Month-Year] = CONVERT(VARCHAR(7), b.Date_Event1, 126) ) as Date_Event1
, ( select sum(case when b.Date_Event2 is null then null else 1 end) from cte b where a.[Month-Year] = CONVERT(VARCHAR(7), b.Date_Event2, 126) ) as Date_Event1
, ( select sum(case when b.Date_Event3 is null then null else 1 end) from cte b where a.[Month-Year] = CONVERT(VARCHAR(7), b.Date_Event3, 126) ) as Date_Event1
, ( select sum(case when b.Date_Event4 is null then null else 1 end) from cte b where a.[Month-Year] = CONVERT(VARCHAR(7), b.Date_Event4, 126) ) as Date_Event1
from yyyydd a
【讨论】:
以上是关于SQL 查询:计数,按月-年分组,具有多个日期字段的主要内容,如果未能解决你的问题,请参考以下文章