Можно ли вывести фиксированное количество групп в SQL, даже если в результате будет меньше групп? - PullRequest
0 голосов
/ 31 марта 2020

Я хочу создать диаграмму на основе запроса SQL. Диаграмма должна отображаться каждые 12 месяцев текущего года, даже если некоторые из них все еще в будущем.

Мой SQL запрос выглядит примерно так:

SELECT
     MONTH (created) as m,
     sum (price) as s
FROM
   product
WHERE
   YEAR (created) = 2020
GROUP BY
   m

Конечно это показывает только результаты за текущий или прошлые месяцы, в которых также есть какие-либо записи.

Можно ли

  • сформулировать запрос так, чтобы в любом случае отображались 12 групп и
  • если группы нет, она получает значение по умолчанию 0?

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

Конечно, осталось присоединить его к коллекции всех 12 месяцев. Это MySQL (потому что вы использовали псевдоним GROUP BY, который, я думаю, только MySQL, может быть, Postgres тоже):

WITH months as (
 SELECT 1 as m
 UNION ALL SELECT 2
 UNION ALL SELECT 3
 UNION ALL SELECT 4
 UNION ALL SELECT 5
 UNION ALL SELECT 6
 UNION ALL SELECT 7
 UNION ALL SELECT 8
 UNION ALL SELECT 9 
 UNION ALL SELECT 10
 UNION ALL SELECT 11
 UNION ALL SELECT 12 
)

SELECT
  m.m,
  sum (p.price) as s
FROM
  months m
  LEFT JOIN product p 
  ON 
    m.m = MONTH(p.created) AND
    p.created > '2020-01-01' and p.Created < '2021-01-01'
GROUP BY
  m.m

Месяцы, которые не совпадают, будут иметь значение NULL, что будет суммироваться как 0

. Вы должны попытаться не использовать такие функции, как YEAR () в предложении WHERE, поскольку они означают, что индексы использовать нельзя; вместо этого оставьте данные таблицы в покое и вместо них поместите поиск по дальности

Если ваш MySQL старый и не поддерживает CTE, сделайте это подзапросом. Если ваша база данных не MySQL / Pg или вам нужно что-то выбрать, вы можете выбрать ее из таблицы, в которой есть только одна строка


Альтернативный трюк, который не использует объединение, будет объединять нагрузку ноль месяцев; они не будут вносить вклад в суммы, но обеспечат месяц 0:

SELECT
   m,
   sum (price) as s
FROM
(
   SELECT MONTH(created) as m, price FROM product WHERE created >= '2020-01-01' and created < '2021-01-01'
   UNION ALL SELECT 1, 0 UNION ALL SELECT 2, 0 UNION ALL SELECT 3, 0 
   UNION ALL SELECT 4, 0 UNION ALL SELECT 5, 0 UNION ALL SELECT 6, 0 
   UNION ALL SELECT 7, 0 UNION ALL SELECT 8, 0 UNION ALL SELECT 9, 0 
   UNION ALL SELECT 10, 0 UNION ALL SELECT 11, 0 UNION ALL SELECT 12, 0 
) x
GROUP BY
   m

Если у вас есть таблица, посвященная числам и датам, блок union all может быть заменен вызовом к нему. Если вы используете Postgres, у него есть последовательный генератор, который может делать крутые вещи

1 голос
/ 31 марта 2020

Вы можете просто создать таблицу для хранения групп, которые вы хотите отобразить.

CREATE TABLE twelveMonths (intMonth int);
INSERT INTO twelveMonths VALUES (1,2,3,4,5,6,7,8,9,10,11,12);

SELECT
     MONTH (created) as m,
     sum(coalesce(price,0)) as s
FROM twelveMonths
LEFT JOIN product ON product.MONTH(created)=twelveMonths.intMonth and YEAR (created) = 2020
    GROUP BY m

Если вы не хотите создавать таблицу, вы можете использовать CTE, временную таблицу или переменную таблицыm или вы можете взломать его с помощью отвратительного подвыбора:

SELECT
     MONTH (created) as m,
     sum(coalesce(price,0)) as s
FROM
      (
   select 1 as intMonth UNION ALL select 2 UNION ALL select 3 UNION ALL select 4 UNION ALL 
   select 5 UNION ALL select 6 UNION ALL select 7 UNION ALL select 8 UNION ALL 
   select 9 UNION ALL select 10 UNION ALL select 11 UNION ALL select 12 ) twelveMonths
LEFT JOIN product ON product.MONTH(created)=twelveMonths.intMonth and YEAR (created) = 2020
GROUP BY m
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...