SQL (postgresql) запрос для извлечения года и суммы - PullRequest
1 голос
/ 05 ноября 2010

Я пытаюсь собрать некоторую простую статистику для таблицы, скажем, упрощенная структура выглядит следующим образом:

  ID  |      CREATIONDATE        |    VALUE    |
------------------------------------------------
  1   | 2007-01-06 13:54:00.000  |      7      |
  2   | 2007-03-07 15:03:00.000  |      8      |
  3   | 2008-07-02 18:55:00.000  |      12     |
  4   | 2008-09-10 19:12:00.000  |      1      |
  5   | 2010-01-06 13:54:00.000  |      4      |
  6   | 2010-01-07 07:13:00.000  |      5      |

Я хотел бы суммировать значения, основанные на годе даты создания, поэтомув настоящее время я выполняю следующее:

select extract('year' from i.creationdate) as d1,
       sum(i.value)
  from items i
  group d1
  order by d1;

, который выдаст

2007;15
2008;13
2010;9

Можно ли как-нибудь улучшить запрос, чтобы он автоматически выводил 0 для отсутствующего 2009 года, даже еслив таблице нет строки с датой в 2009 году?

2007;15
2008;13
2009;0
2010;9

Ответы [ 4 ]

3 голосов
/ 05 ноября 2010

Использовать generate_series в JOIN:

SELECT 
    generate_series as d1, 
    COALESCE(sum(i.value) , 0)
FROM 
    generate_series(2005, 2010) 
        LEFT JOIN items i ON generate_series = extract('year' from i.creationdate)
GROUP BY
    d1 
ORDER BY
    d1;
3 голосов
/ 05 ноября 2010

Используйте левое внешнее объединение из генерирующей серии

select year_list.year,
       coalesce(item_list.val,0)
 from (select generate_series(2007,2010) as year) AS year_list
       left outer join
      (select date_part('year',creationdate) item_year,sum(value) as val from i group by item_year) AS item_list 
      on item_year = year_list.year;     

, чтобы избежать жесткого кодирования лет в generate_series, вместо подстановки выберите min () и max () для части года.

1 голос
/ 05 ноября 2010

Я бы сделал бы это в программном обеспечении , которое выполняет запрос, в отличие от самого запроса.

Я делал такие вещи (например, в Oracle), используя циклы forв SQL (без сомнения, в Postgres есть подобные вещи), однако я пришел к выводу, что это был неправильный подход.Решение было труднее поддерживать, чем если бы я просто написал код на языке программирования приложения.

SQL возвращает данные, которые существуют, и оперирует данными, которые существуют, и в этом случае нет данныхза рассматриваемый год.Вот почему не стоит пытаться заставить SQL делать это.Просто спросите SQL для данных, которые у вас есть, и когда вы генерируете выходные данные на своем языке программирования для пользователя (например, таблица HTML), затем добавьте цикл for для итерации между первым и последним годом и выведите ноль, если результата нет.

0 голосов
/ 05 ноября 2010

Простой (но не очень) способ - создать (временную) таблицу, содержащую все годы в одном столбце.Затем вы просто присоединяете таблицу данных к новой таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...