web-dev-qa-db-ja.com

1つの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にとって正しい用語を理解できません。

9
Bryan

各数値範囲の列ごとに条件付きSUM()ステートメントを使用するだけです。合計は、SUM(1)を使用して合計できます。テーブル内のすべてのデータが範囲の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リンク

7
Philᵀᴹ

Postgres 9.4以降の集約FILTER

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は、NULLまたは他の値が関係しない限り、lowmidおよび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;
_

少し短く、やや速い。

微妙な違い

Phil's answersum()と比較すると、微妙な違いがあります

  • 最も重要なのは、 ドキュメントごと

    count以外の行が選択されていない場合、これらの関数はnull値を返すことに注意してください。特に、行がないsumは、期待どおりにゼロではなくnullを返します...

  • count(*)is標準的な方法で、sum(1)よりも少し高速です。この場合も、nullと0が適用されます。

これらのクエリ(フィルのクエリを含む)は、totalのnull値をカウントします。それが望ましくない場合は、代わりに使用してください:

_count(score) AS total_not_null
_

SQL Fiddle 9.3ページ。
db <> fiddle here(10ページ).

8