PostgreSQL查询未显示全部行:如何统计含0值的子公司月度发票数
解决子公司发票统计时显示全部子公司的问题
你的核心问题是WHERE条件过滤掉了无发票子公司的行,同时第二个查询的表顺序错误,导致无法包含无发票的子公司。以下是具体调整方案:
问题根源
- 第一个查询中,
WHERE i.created_at >= '2022-09-01' AND i.created_at <= '2022-09-30'会过滤掉所有i.created_at为NULL的行(也就是没有对应发票的子公司),因为NULL无法满足时间范围条件,导致这些子公司被排除。 - 第二个查询从
invoices表开始左关联,没有发票的子公司不会出现在关联结果中,自然无法被统计。
正确查询方案
方案一:将时间条件移至JOIN子句
把发票的时间过滤条件放到LEFT JOIN invoices的ON子句中,而不是全局的WHERE条件,这样只会关联符合时间的发票,不会过滤掉子公司本身:
SELECT s.id, s.name, COALESCE(COUNT(i.id), 0) AS sep_22 FROM subsidiaries s LEFT JOIN users u ON s.id = u.subsidiary_id LEFT JOIN invoices i ON u.id = i.user_id AND i.created_at >= '2022-09-01' AND i.created_at <= '2022-09-30' GROUP BY s.id, s.name;
方案二:使用CASE表达式统计(更直观)
通过CASE表达式判断发票是否符合时间范围,再用SUM统计数量,无需担心NULL过滤问题:
SELECT s.id, s.name, SUM(CASE WHEN i.created_at >= '2022-09-01' AND i.created_at <= '2022-09-30' THEN 1 ELSE 0 END) AS sep_22 FROM subsidiaries s LEFT JOIN users u ON s.id = u.subsidiary_id LEFT JOIN invoices i ON u.id = i.user_id GROUP BY s.id, s.name;
说明
- 必须从
subsidiaries表作为查询起点,确保所有子公司都被包含。 - 方案一中
COUNT(i.id)会自动统计非NULL的发票数量,无发票时为0,COALESCE是为了确保极端情况(如子公司无用户也无发票)下显示0。 - 方案二中
SUM(CASE...)直接对符合条件的发票计数,逻辑更清晰,无需额外处理NULL。
内容的提问来源于stack exchange,提问作者NaguiHW
相关产品推荐
相关产品推荐

