Выберите все месяцы в пределах указанного диапазона, в том числе те, которые имеют 0 значений - PullRequest
5 голосов
/ 22 июня 2010

Я пытаюсь написать запрос MySQL, чтобы получить среднее значение за месяц, для всех месяцев между указанными датами. Моя идея такова:

Запрос, что-то вроде

SELECT AVG(value1) as avg_value_1, 
AVG(value2) as avg_value_2, 
MONTH(save_date) as month, 
YEAR(save_date) as year
FROM myTable
WHERE save_date BETWEEN '2009-01-01' AND '2009-07-01'
GROUP BY YEAR(save_date), MONTH(save_date)

avg_value_1 | avg_value_2 | month | year
     5      |      4      |   1   | 2009
     2      |      1      |   2   | 2009
     7      |      5      |   3   | 2009
     0      |      0      |   4   | 2009 <---
     6      |      5      |   5   | 2009
     3      |      6      |   6   | 2009

Видите ли, в апреле 2009 года не было введено никаких значений, но я хочу, чтобы оно отображалось как 0, 0 в выходных данных. Есть идеи как этого добиться? Можно ли это сделать в MySQL?

Ответы [ 2 ]

6 голосов
/ 24 июня 2010

Я согласен с ответом Ливена: создайте таблицу, содержащую все месяцы, которые вам когда-либо понадобятся, и используйте ее, чтобы "СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ" к вашей таблице результатов.Помните, это действительно крошечная таблица, только 365 (иш) строк в год данных, которые у вас есть ... И вы можете легко написать некоторый код, чтобы заполнить эту таблицу изначально

Мы делаем это здесь, и это даетмного преимуществ, например, представьте ежемесячную таблицу данных со следующими полями (и любыми другими, которые вы можете придумать!), полностью заполненными для всех месяцев в данном диапазоне;

  • Дата (например, 2009 г.)-04-01)
  • День (например, 1)
  • День недели (например, среда)
  • Месяц (например, 4)
  • Год (например, 2009 г.))
  • Финансовый год (например, 2009/10)
  • Финансовый квартал (например, 2009Q1)
  • Календарный квартал (например, 2009Q2)

Затем объединениеэто с вашим запросом выше, как показано ниже:

SELECT `DT`.`myYear`, `DT`.`myMonth`, 
           AVG(`myTable`.`value1`) as avg_value_1, 
           AVG(`myTable`.`value2`) as avg_value_2

FROM `dateTable` as DT
LEFT JOIN `myTable`
    ON `dateTable`.`myDate` = `myTable`.`save_date`

WHERE `dateTable`.`myDate` BETWEEN '2009-01-01' AND '2009-07-01'

GROUP BY `DT`.`myYear`, `DT`.`myMonth`

В моем коде SQL могут быть некоторые ошибки, так как я не смог создать тестовые таблицы, но, надеюсь, вы получите принципал и изменитев соответствии с вашими потребностями!

Используя это, вы можете изменить свое предложение "GROUP BY" на то, что у вас есть в "dateTable"таблица, которая позволяет легко составлять отчеты по финансовому кварталу, месяцу, дню, дню недели и т. д.

Надеюсь, это поможет!

2 голосов
/ 22 июня 2010

Самый простой способ, вероятно, состоит в том, чтобы создать таблицу дат, содержащую месяцы и годы, и объединить ее с вашим окончательным результатом.

...