Rückgabewerte für mehrere Bereiche in einer einzelnen SELECT-Anweisung


9

Ich habe eine Postgres-Datenbanktabelle foo, die unter anderem eine Spalte für scorediesen Bereich von 0 bis 10 enthält. Ich möchte, dass eine Abfrage die Gesamtzahl der Bewertungen, die Anzahl der Bewertungen zwischen 0 und 3 und die Anzahl der Bewertungen zwischen 4 zurückgibt und 6 und die Anzahl der Punkte zwischen 7 und 10. So etwas wie das Folgende:

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;

Ich habe es versucht, habe aber einen Fehler mit den SELECTin den COUNTAnweisungen. Irgendwelche Ideen, wie ich das machen kann? Ich bin mir sicher, dass es in Postgres einen super einfachen Weg gibt. Ich kann einfach nicht die richtigen Begriffe für Google herausfinden.

Antworten:


7

Verwenden Sie einfach bedingte SUM()Anweisungen pro Spalte für jeden Nummernkreis. Die Summe kann durch einfaches Verwenden summiert werden SUM(1), vorausgesetzt, alle Daten in der Tabelle liegen innerhalb eines der Bereiche - wenn nicht, beschränken Sie sie einfach wie bei den anderen.

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 Link .


8

Aggregatklausel FILTERin Postgres 9.4+

Seit Postgres 9.4 gibt es einen sauberen und schnellen Weg (SQL-Standard):

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;

totaladdiert low, midund highes sei denn , NULL oder andere Werte beteiligt sind.

Links:

Lesen Sie auch unten.

Postgres 9.3-

Es gibt einige Techniken:

@Phil hat den Standardweg mit einer CASEAnweisung versehen (außer sum(1), was nicht der Standardweg ist). Ich benutze gerne eine kürzere Form:

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;

Wenn Ihre Werte wie in Ihrer Frage definiert sind (nur 0- 10möglich), vereinfachen Sie dies weiter:

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;

Ein bisschen kürzer, kaum schneller.

Feine Unterschiede

Es gibt feine Unterschiede im Vergleich zu dem sum()in Phils Antwort :

  • Am wichtigsten ist laut Dokumentation :

    Es ist zu beachten, dass countdiese Funktionen mit Ausnahme von einen Nullwert zurückgeben, wenn keine Zeilen ausgewählt sind. Insbesondere gibt sumkeine Zeile null zurück, nicht null, wie man erwarten könnte, ...

  • count(*) ist der Standardweg und etwas schneller als sum(1). Auch hier gilt null gegen 0.

Jede dieser Abfragen (einschließlich der von Phil) zählt Nullwerte für total. Wenn dies nicht wünschenswert ist, verwenden Sie stattdessen:

count(score) AS total_not_null

SQL Fiddle in S. 9.3.
db <> Geige hier in S. 10.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.