Postgresql
在單個 SELECT 語句中返回多個範圍的計數
我有一個 Postgres 數據庫表
foo
,其中有一列score
範圍從 0 到 10。我想要一個查詢來返回總分數、0 到 3 之間的分數數、4 之間的分數數和 6,以及 7 到 10 之間的分數。類似於以下內容:SELECT COUNT(*) as total, COUNT( SELECT * from foo where score between 0 and 3; ) as low, COUNT( SELECT * from foo where score between 4 and 6; ) as mid, COUNT( SELECT * from foo where score between 7 and 10; ) as high FROM foo;
SELECT
我試過這個,但在COUNT
語句中出現錯誤。任何想法我怎麼能做到這一點?我確信在 Postgres 中有一個超級簡單的方法。我只是想不出Google的正確條款。
只需
SUM()
為每個數字範圍的每列使用條件語句。SUM(1)
假設表中的所有數據都在某個範圍內,則只需使用 就可以對總數進行求和- 如果不是,則將其與其他數據一樣進行限制。select sum(case when score between 0 and 3 then 1 else 0 end) as minrange, sum(case when score between 4 and 6 then 1 else 0 end) as midrange, sum(case when score between 7 and 10 then 1 else 0 end) as maxrange, sum(1) as total from foo;
FILTER
Postgres 9.4+ 中的聚合子句從 Postgres 9.4 開始,有一種干淨快速(SQL 標準)的方式:
SELECT count(*) FILTER (WHERE score BETWEEN 0 AND 3) AS low , count(*) FILTER (WHERE score BETWEEN 4 AND 7) AS mid , count(*) FILTER (WHERE score BETWEEN 8 AND 10) AS high , count(*) AS total FROM foo;
total
加起來和low
,除非涉及 NULL 或其他值。mid``high
連結:
另請閱讀下文。
Postgres 9.3-
有幾個技巧:
@Phil提供了一個帶有
CASE
語句的通用替代方法(除了sum(1)
,這不是標準方式)。我喜歡使用更短的形式:SELECT count(score BETWEEN 0 AND 3 OR NULL) AS low , count(score BETWEEN 4 AND 6 OR NULL) AS mid , count(score BETWEEN 7 AND 10 OR NULL) AS high , count(*) AS total FROM foo;
如果您的值與您的問題中定義的一樣(僅
0
-10
可能),請進一步簡化:SELECT count(score < 4 OR NULL) AS low , count(score BETWEEN 4 AND 6 OR NULL) AS mid , count(score > 6 OR NULL) AS high , count(*) AS total FROM foo;
稍微短一點,快一點。
細微差別
與菲爾的回答相比,存在細微的差異:
sum()
- 最重要的是,根據文件:
需要注意的是,除了 之外
count
,這些函式在沒有選擇行時返回空值。特別是,sum
of no rows 返回 null,而不是預期的零,…
count(*)
是標準方式,比sum(1)
. 同樣,null vs. 0 適用。這些查詢中的任何一個(包括 Phil 的)都將
total
. 如果這不是可取的,請改用:count(score) AS total_not_null
db<>fiddle here
舊sqlfiddle (pg 9.3)