SQL中替代CASE语句实现分区域价格对比汇总的方案咨询
问题背景
现有结构如下的数据库表:
-------------------------------- region | price_a | price_b -------------------------------- USA | 100 | 120 USA | 150 | 150 Canada | 300 | 300 Mexico | 20 | 25
需要对比每行price_a和price_b的取值,按region分组统计价格匹配、不匹配的行数,期望输出如下:
-------------------------------- region | price_match | price_mismatch -------------------------------- USA | 1 | 1 Canada | 1 | 0 Mexico | 0 | 1
目前已实现的多CASE语句方案如下:
SELECT region, COUNT(CASE WHEN price_a = price_b THEN 'match' END) AS price_match, COUNT(CASE WHEN price_a != price_b THEN 'match' END) AS price_mismatch FROM FOO GROUP BY region;
更优实现方案
有几种比重复写完整CASE语句更简洁、可读性更好的实现方式,性能和原有方案一致,都只需要单次扫描表完成统计:
- 通用SQL兼容方案:用SUM+布尔表达式
适配MySQL、PostgreSQL等支持布尔表达式直接返回1/0的数据库,代码更短:
如果是不支持布尔值直接转数字的数据库(比如Oracle、SQL Server),可以简化CASE结构为1/0返回,逻辑比原写法更直观:SELECT region, SUM(price_a = price_b) AS price_match, SUM(price_a != price_b) AS price_mismatch FROM FOO GROUP BY region;SELECT region, SUM(CASE WHEN price_a = price_b THEN 1 ELSE 0 END) AS price_match, SUM(CASE WHEN price_a != price_b THEN 1 ELSE 0 END) AS price_mismatch FROM FOO GROUP BY region; - PostgreSQL专属方案:用FILTER子句
语法语义最清晰,符合标准SQL的条件聚合规范:SELECT region, COUNT(*) FILTER (WHERE price_a = price_b) AS price_match, COUNT(*) FILTER (WHERE price_a != price_b) AS price_mismatch FROM FOO GROUP BY region;
内容的提问来源于stack exchange,提问作者FunnyChef
相关产品推荐
相关产品推荐

