如何编写SQL查询统计今日各类型记录并返回所有类型(含无数据)
解决SQL查询包含所有类型(含今日无记录)的统计问题
你的现有查询只能返回今日有记录的类型,没法包含那些今日没有产生记录的类型——因为WHERE条件先过滤掉了非今日的数据,分组后自然不会出现无记录的类型。要实现包含所有类型的统计,得用左连接先获取全量类型,再关联今日数据统计。
两种实现方案
1. 有专门的类型字典表(推荐)
如果你的系统里有专门存储所有记录类型的表(比如status_types,包含status字段),可以直接用它做左连接:
SELECT st.status, COUNT(hl.id) AS record_count FROM status_types st LEFT JOIN http_log hl ON st.status = hl.status AND CAST(hl.created_at AS DATE) = CAST(current_date AS DATE) GROUP BY st.status ORDER BY st.status;
- 要点:把日期条件放在
JOIN里而非WHERE,这样不会过滤掉左表中无匹配的类型行;COUNT(hl.id)会对无匹配的行返回0(因为hl.id为NULL,COUNT会忽略NULL值)。
2. 无专门类型表,从日志表提取全量类型
如果没有单独的类型表,可以先从http_log里提取所有历史出现过的类型,再做左连接:
WITH all_statuses AS ( SELECT DISTINCT status FROM http_log ) SELECT as.status, COUNT(hl.id) AS record_count FROM all_statuses as LEFT JOIN http_log hl ON as.status = hl.status AND CAST(hl.created_at AS DATE) = CAST(current_date AS DATE) GROUP BY as.status ORDER BY as.status;
- 用CTE(
WITH子句)先获取去重后的所有类型,再关联今日数据统计,效果和第一种一致。
额外需求:同时获取今日记录值
如果还要展示每个类型今日的具体记录值(比如把记录值拼接成字符串),可以用字符串聚合函数(不同数据库函数名可能不同,以下是PostgreSQL示例):
SELECT st.status, COUNT(hl.id) AS record_count, STRING_AGG(hl.record_value, ', ') AS today_records FROM status_types st LEFT JOIN http_log hl ON st.status = hl.status AND CAST(hl.created_at AS DATE) = CAST(current_date AS DATE) GROUP BY st.status ORDER BY st.status;
把record_value替换成你表中存储记录值的实际字段名即可。
内容的提问来源于stack exchange,提问作者Abdulrahman Shalabi
相关产品推荐
相关产品推荐

