选择具有不同条件的多列

Bri*_*hah 5 sql postgresql select count

具有以下字段的用户表。

id
agent_id
locality
total
building_type
price
Run Code Online (Sandbox Code Playgroud)

我通过以下查询得到不同的统计结果

SELECT agent_id, COUNT(*) AS stat_1 
FROM users 
WHERE "building_type" = 'single' 
AND ("price" BETWEEN 0 AND 200000) 
GROUP BY "agent_id" 
order by agent_id

SELECT agent_id, COUNT(*) AS stat_2 
FROM users 
WHERE "building_type" = 'single' 
AND ("price" BETWEEN 200001 AND 350000) 
GROUP BY "agent_id" 
order by agent_id

SELECT agent_id, COUNT(*) AS stat_3 
FROM users 
WHERE "building_type" = 'single' 
AND ("price" BETWEEN 3500001 AND 500000) 
GROUP BY "agent_id" 
order by agent_id
Run Code Online (Sandbox Code Playgroud)

但我想在同一查询中获得所有统计数据的结果,例如

SELECT agent_id, 
       COUNT(*) AS stat_1, 
       COUNT(*) AS stat_2, 
       COUNT(*) AS stat_3 
from users 
where <Conditions>
Run Code Online (Sandbox Code Playgroud)

如何在一次查询中获得此结果?

Mur*_*nik 8

Postgres 9.4 通过添加一个子句以一种优雅的方式解决了此类问题,filter该子句允许您对聚合函数应用条件:

SELECT   agent_id, 
         COUNT(*) FILTER (WHERE "price" BETWEEN 0 AND 200000) AS stat_1,
         COUNT(*) FILTER (WHERE "price" BETWEEN 200001 AND 350000) AS stat_2,
         COUNT(*) FILTER (WHERE "price" BETWEEN 3500001 AND 500000) AS stat_3
FROM     users 
WHERE    "building_type" = 'single' 
GROUP BY "agent_id" 
ORDER BY "agent_id"
Run Code Online (Sandbox Code Playgroud)

对于不允许使用子句的早期版本filter,您可以通过将聚合函数应用于表达式来自行实现相同的行为case。这里,我们利用 的count忽略 s 的性质null

SELECT   agent_id, 
         COUNT(CASE WHEN "price" BETWEEN 0 AND 200000 THEN 1 END) AS stat_1,
         COUNT(CASE WHEN "price" BETWEEN 200001 AND 350000 THEN 1 END) AS stat_2,
         COUNT(CASE WHEN "price" BETWEEN 3500001 AND 500000 THEN 1 END) AS stat_3
FROM     users 
WHERE    "building_type" = 'single' 
GROUP BY "agent_id" 
ORDER BY "agent_id"
Run Code Online (Sandbox Code Playgroud)


小智 3

您可以使用条件聚合:

SELECT agent_id, 
       COUNT(*) filter (where price BETWEEN 0 AND 200000) as stat_1,
       COUNT(*) filter (where price BETWEEN 200001 AND 350000)  AS stat_2, 
       COUNT(*) filter (where price BETWEEN 3500001 AND 500000)  AS stat_3 
from users 
WHERE building_type = 'single' 
GROUP BY agent_id
order by agent_id
Run Code Online (Sandbox Code Playgroud)