在单个SELECT语句中返回多个范围的计数


9

我有一个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;

我想这一点,但与得到一个错误SELECTCOUNT语句。有什么想法可以做到吗?我敢肯定Postgres中有一种超级简单的方法。我只是想不出正确的字词给Google。

Answers:


7

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;

SQL Fiddle链接


8

FILTERPostgres 9.4+中的Aggregate 子句

从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加起来lowmid并且high,除非NULL或其他值都参与。

链接:

另请阅读以下内容。

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没有行会返回null,而不是像预期的那样返回零,...

  • count(*) 标准方式,比sum(1)。同样,适用null与0。

这些查询中的任何一个(包括Phil在内)都为计数空值total。如果不希望这样,请改用:

count(score) AS total_not_null

第9.3页中的 SQL Fiddle
分贝<>小提琴这里在第10页。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.