如何在Oracle SQL查询中返回COUNT为0的日期与状态组合行?
实现日期与状态全组合的统计(含0值)
当然可以实现你的需求!问题出在你原来的SQL只会统计表中实际存在的日期+状态组合,那些没有对应数据的组合自然不会出现在结果里。要得到包含0值的全组合,我们需要先生成所有可能的日期+状态配对,再和实际统计结果做左连接来补全0值。
解决思路
- 提取表中所有去重的日期;
- 提取所有可能的状态(这里只有STATUS1和STATUS2,也可以直接手动构造);
- 用
CROSS JOIN生成日期和状态的笛卡尔积(即所有可能的组合); - 左连接原表的分组统计结果,用
NVL()把NULL转换为0。
完整SQL代码
WITH -- 第一步:获取所有存在的日期(去重) distinct_dates AS ( SELECT DISTINCT TO_CHAR(CREATED_ON, 'DD-MM-YY') AS doc_date FROM DOCUMENTS ), -- 第二步:获取所有可能的状态(两种方式二选一即可) -- 方式一:从表中去重提取(适合状态可能变动的场景) all_statuses AS ( SELECT DISTINCT STATUS FROM DOCUMENTS ) -- 方式二:手动构造(适合状态固定为两个的场景) -- all_statuses AS ( -- SELECT 'STATUS1' AS status FROM DUAL -- UNION ALL -- SELECT 'STATUS2' AS status FROM DUAL -- ) -- 第三步:生成全组合并左连接统计结果 SELECT dd.doc_date AS DATE, as_.status AS STATUS, NVL(dc.total, 0) AS TOTAL FROM distinct_dates dd CROSS JOIN all_statuses as_ LEFT JOIN ( -- 原表的基础统计逻辑 SELECT TO_CHAR(CREATED_ON, 'DD-MM-YY') AS doc_date, STATUS, COUNT(*) AS total FROM DOCUMENTS GROUP BY TO_CHAR(CREATED_ON, 'DD-MM-YY'), STATUS ) dc ON dd.doc_date = dc.doc_date AND as_.status = dc.status ORDER BY dd.doc_date ASC, as_.status ASC;
代码说明
CROSS JOIN会把每个日期和每个状态进行配对,生成完整的日期-状态组合;LEFT JOIN确保即使某个组合在原表中没有数据,也会保留该组合行;NVL(dc.total, 0)将左连接后没有匹配到的NULL值替换为0,完全符合你的需求。
执行这段SQL后,就能得到你期望的包含0值的统计结果了。
内容的提问来源于stack exchange,提问作者loliveira1999
相关产品推荐
相关产品推荐

