SQL查询:计数,按年份和多个日期字段分组

时间:2020-01-30 19:26:33

标签: sql postgresql date amazon-redshift

我有一个看起来像下面的表格,其中所有列都是记录特定操作日期的日期字段。假设有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      |

关于从哪里开始的想法并不多

2 个答案:

答案 0 :(得分:0)

下面是一个示例,该示例将对每个列进行子查询。

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

答案 1 :(得分:0)

您可以将其扩展到更多列

对于 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 
相关问题