如何无需CTE或连接,在窗口函数中使用CASE表达式实现日历统计
用COUNT窗口函数实现时间区间天数统计(无需CTE/连接)
完全可以实现,核心逻辑是直接在COUNT窗口函数的PARTITION BY子句中使用计算年季度、半年的原始表达式,无需依赖SELECT列表里定义的别名,这样就不用额外的CTE或连接操作。
以下是针对2022年日历的示例SQL,直接通过窗口函数完成各时间维度的天数统计:
SELECT date AS calendar_date, EXTRACT(YEAR FROM date) AS year, EXTRACT(MONTH FROM date) AS month, -- 生成年季度标识 CONCAT(EXTRACT(YEAR FROM date), 'Q', CEIL(EXTRACT(MONTH FROM date)/3)) AS year_quarter, -- 生成半年标识 CONCAT(EXTRACT(YEAR FROM date), 'H', CASE WHEN EXTRACT(MONTH FROM date) <=6 THEN 1 ELSE 2 END) AS year_half, -- 月度天数统计 COUNT(*) OVER(PARTITION BY EXTRACT(YEAR FROM date), EXTRACT(MONTH FROM date)) AS year_month_days_cnt, -- 季度天数统计:直接用季度计算逻辑作为分区键 COUNT(*) OVER(PARTITION BY EXTRACT(YEAR FROM date), CEIL(EXTRACT(MONTH FROM date)/3)) AS year_quarter_days_cnt, -- 半年天数统计:直接用半年计算逻辑作为分区键 COUNT(*) OVER(PARTITION BY EXTRACT(YEAR FROM date), CASE WHEN EXTRACT(MONTH FROM date) <=6 THEN 1 ELSE 2 END) AS year_half_days_cnt, -- 全年天数统计 COUNT(*) OVER(PARTITION BY EXTRACT(YEAR FROM date)) AS year_days_cnt FROM GENERATE_SERIES('2022-01-01'::DATE, '2022-12-31'::DATE, '1 day'::INTERVAL) AS t(date);
关键说明
- 窗口函数的
PARTITION BY允许直接使用字段计算表达式,不需要引用SELECT里的别名(SQL解析时,窗口函数的执行逻辑晚于SELECT列表的字段计算,但PARTITION BY可以独立使用底层字段的计算逻辑)。 - 示例中用
GENERATE_SERIES生成2022年的所有日期,你可以替换成自己的日历表数据源。
内容的提问来源于stack exchange,提问作者Ramzes
相关产品推荐
相关产品推荐

