如何组合两个SQL查询按alive/dead新分组名输出统计结果
人员存活状态饼图统计SQL实现
原查询的核心错误
- NULL判断语法不符合SQL规范:判断字段值是否为NULL必须使用
IS NULL/IS NOT NULL,使用= NULL做等值比较的结果永远为UNKNOWN,无法匹配到任何数据,原查询里deceased = NULL、NOT deceased = NULL的写法完全失效 - 条件逻辑因优先级偏差出错:
AND的运算优先级高于OR,原查询的多条件组合未添加括号拆分逻辑分支,实际执行的判断范围和预期不符 - 统计边界存在重叠/遗漏:原查询没有明确划定alive和dead的互斥范围,容易出现同一人员被重复统计、无效记录被错误分类的问题
最优实现方案(完全适配现有饼图脚本)
使用CASE语句直接生成状态标签,再按状态分组聚合,仅需一次表扫描即可输出和性别、国籍统计完全一致的两列结构,无需修改现有PHP脚本:
SELECT CASE -- 匹配存活判定规则:死亡日期为NULL/默认空日期,且出生日期非默认空日期 WHEN (deceasedDate IS NULL OR deceasedDate = '0000-00-00') AND bornDate != '0000-00-00' THEN 'alive' -- 其余所有记录自动归类为dead ELSE 'dead' END AS status, COUNT(*) AS person_count FROM persons GROUP BY status ORDER BY person_count DESC;
该查询直接输出符合要求的两行结构,示例输出为:
- alive | 16
- dead | 4
沿用原独立查询思路的UNION实现
若需要保留拆分判断存活、死亡状态的查询逻辑,需先修正原查询的语法、逻辑错误,再通过UNION整合统计结果,两个分支的统计范围必须完全互斥,避免重复计数:
-- 统计存活人数 SELECT 'alive' AS status, COUNT(*) AS person_count FROM persons WHERE (deceasedDate IS NULL OR deceasedDate = '0000-00-00') AND bornDate != '0000-00-00' UNION ALL -- 统计死亡人数 SELECT 'dead' AS status, COUNT(*) AS person_count FROM persons WHERE (deceasedDate IS NOT NULL AND deceasedDate != '0000-00-00') OR bornDate = '0000-00-00';
注意:UNION方案需要两次扫描业务表,性能低于单次扫描的CASE分组方案;使用时需校验两个查询的计数总和与表内总人数一致,避免出现范围重叠、遗漏的问题。
内容的提问来源于stack exchange,提问作者Robbas
相关产品推荐
相关产品推荐

