Підрахунок повернень для декількох діапазонів в одному операторі 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;

Я спробував це, але отримав повідомлення про помилку з SELECTв COUNTзвітності. Будь-які ідеї, як я можу це зробити? Я впевнений, що у Postgres є дуже простий спосіб. Я просто не можу з’ясувати правильні умови для Google.

Відповіді:


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 Скрипки посилання .


8

Сукупна 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, midі 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жоден рядок не повертає нуля, а не нуля, як можна було очікувати, ...

  • count(*) це стандартний спосіб і трохи швидше, ніж sum(1). Знову ж таки, застосовується null vs. 0.

Будь-який із цих запитів (включаючи Філа) враховує нульові значення для total. Якщо це не бажано, використовуйте натомість:

count(score) AS total_not_null

SQL Fiddle в pg 9.3.
db <> скрипка тут, на сторінці 10.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.