выбор между диапазоном дат и установление пустых строк в 0? - PullRequest
3 голосов
/ 15 июня 2011

У меня есть таблица, которая выглядит как

expires    | value  
-------------------
2011-06-15 | 15  
2011-06-15 | 15  
2011-06-25 | 15  
2011-07-15 | 15  
2011-07-15 | 15  
2011-07-25 | 15  
2011-08-15 | 15  
2011-08-15 | 15  
2011-08-25 | 15

Я хочу выполнить запрос, который будет выплевывать

June   | 45  
July   | 45  
August | 45  

Итак, мой запрос

  SELECT SUM(amount) AS `amount`, 
         DATE_FORMAT(expires , '%M') AS `month`  
    FROM dealDollars 
   WHERE DATE(expires) BETWEEN DATE(NOW()) 
                           AND LAST_DAY(DATE(NOW()+INTERVAL 3 MONTH)) 
GROUP BY MONTH(expires)

Который работает отлично.Но в результате, если бы в июле не было строк, июль не был бы обнаружен.

Как я могу заставить июль отображаться с 0 в качестве значения?

Ответы [ 4 ]

4 голосов
/ 15 июня 2011

Нет простого способа сделать это.Один из возможных способов - создать таблицу с названием month: в ней будет 12 строк: (январь, февраль, ..., декабрь)

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

1 голос
/ 15 июня 2011

MySQL не имеет рекурсивной функциональности, поэтому вам остается использовать NUMBERS табличный трюк -

  1. Создать таблицу, содержащую только инкрементные числа - это легко сделать с помощью auto_increment:

    DROP TABLE IF EXISTS `example`.`numbers`;
    CREATE TABLE  `example`.`numbers` (
      `id` int(10) unsigned NOT NULL auto_increment,
       PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
  2. Заполните таблицу, используя:

    INSERT INTO NUMBERS
      (id)
    VALUES
      (NULL)
    

    ... для столько значений, сколько вам нужно. В этом случае оператор INSERT должен выполняться не менее 3 раз.

  3. Используйте DATE_ADD , чтобы составить список дней, увеличивая на основе значения NUMBERS.id:

    SELECT x.dt
      FROM (SELECT DATE(DATE_SUB(CURRENT_DATE(), INTERVAL (n.id - 1) MONTH)) AS dt
              FROM numbers n
             WHERE DATE(DATE_SUB(CURRENT_DATE(), INTERVAL (n.id - 1) MONTH)) BETWEEN CURRENT_DATE()
                                                                                 AND LAST_DAY(CURRENT_DATE() +INTERVAL 3 MONTH))  ) x
    
  4. Используйте OUTER JOIN для получения желаемого результата:

       SELECT x.dt,
              COUNT(*) AS total
         FROM (SELECT DATE(DATE_SUB(CURRENT_DATE(), INTERVAL (n.id - 1) MONTH)) AS dt
              FROM numbers n
             WHERE DATE(DATE_SUB(CURRENT_DATE(), INTERVAL (n.id - 1) MONTH)) BETWEEN CURRENT_DATE()
                                                                                 AND LAST_DAY(CURRENT_DATE() +INTERVAL 3 MONTH))  ) x
    LEFT JOIN YOUR_TABLE y ON y.date = x.dt
     GROUP BY x.dt
     ORDER BY x.dt
    

Почему числа, а не даты?

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

1 голос
/ 15 июня 2011

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

Вам нужно будет поработать над спецификой самостоятельно, но вы смотрели на подзапросы в предложении from ?

В принципе, это было бы что-то вроде этого:

SELECT NVL(B.amount, 0) as `amount`, A.month as `month`
      FROM (SELECT 'January' as `month`
            UNION SELECT 'February' as `month`
            UNION SELECT 'March' as `month`...
            UNION SELECT 'DECEMBER' as `month`) as A
      LEFT JOIN
            (SELECT SUM(amount) AS `amount`, 
                    DATE_FORMAT(expires , '%M') AS `month`  
               FROM dealDollars 
               WHERE 
                  DATE(expires) BETWEEN 
                       DATE(NOW()) AND 
                       LAST_DAY(DATE(NOW()+INTERVAL 3 MONTH)) 
               GROUP BY MONTH(expires)) as B
            ON (A.MONTH = B.MONTH)

Сумасшедший, нет?

0 голосов
/ 29 июля 2013
select MONTHNAME(expires) as month_name,sum(`value`) from Table1
group by month_name order by null;

скрипка

...