另一个稍短的变体(性能与CASE
语句大致相同):
SELECT pc.dist_id, pc.route, pc.types
,COUNT(NULLIF(pc.types = '$type', FALSE) AS total
,COUNT(NULLIF(pc.types = '$type' AND pc.options = '1', FALSE) AS callbacks
FROM per_call pc
WHERE pc.types = '$type'
GROUP BY pc.dist_id, pc.route, pc.types
ORDER BY pc.dist_id, pc.route;
它背后的原理是:
COUNT
计算所有非空值。
表达式产生一个布尔值,它可以是TRUE
,FALSE
或NULL
。
您只想计算TRUE
案件。
所以转换FALSE
为NULL
,一切都很时髦。
或者,甚至更短,但不是更快:
SELECT pc.dist_id, pc.route, pc.types
,sum((pc.types = '$type')::int) AS total
,sum((pc.types = '$type' AND pc.options = '1')::int) AS callbacks
FROM per_call pc
WHERE pc.types = '$type'
GROUP BY pc.dist_id, pc.route, pc.types
ORDER BY pc.dist_id, pc.route;
强制boolean
转换为 1,转换integer
为0。因此,有效。TRUE
FALSE
sum()
既然你有pc.types = '$type'
asWHERE
条件,你可以简化为:
SELECT pc.dist_id, pc.route, pc.types
,COUNT(*) AS total -- slightly faster, too
,COUNT(NULLIF(pc.options = '1', FALSE) AS callbacks
FROM per_call pc
WHERE pc.types = '$type'
GROUP BY pc.dist_id, pc.route, pc.types
ORDER BY pc.dist_id, pc.route;