Группировка по дате, возврат строки, даже если записи не найдены - PullRequest
4 голосов
/ 04 сентября 2010

У меня есть запрос, который группирует все записи из таблицы и группирует их по столбцу datetime.Все это прекрасно работает:

SELECT SUM(  `value` ) AS  `sum` , DATE(`datetime`) AS  `dt``
FROM  `entry` 
WHERE entryid = 85
AND DATETIME BETWEEN  '2010-01-01' AND '2010-03-01'
GROUP BY `dt`
ORDER BY `datetime`

Проблема в том, что мне нужно вернуть строку, даже если ничего не найдено, со значением, установленным в 0. Я предполагаю, что есть какой-то MYSQLфункция, которая позаботится об этом, но не может найти ее.

Спасибо!

1 Ответ

8 голосов
/ 04 сентября 2010

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)
    

    ... для столько значений, сколько вам нужно.

  3. Используйте DATE_ADD для построения списка дат, увеличивая дни на основе значения NUMBERS.id. Замените «2010-01-01» и «2010-03-01» на соответствующие даты начала и окончания (но используйте один и тот же формат, ГГГГ-ММ-ДД) -

    SELECT x.*
      FROM (SELECT DATE_ADD('2010-01-01', INTERVAL n.id - 1 DAY)
              FROM numbers n
             WHERE DATE_ADD('2010-01-01', INTERVAL n.id -1 DAY) <= '2010-03-01' ) x
    
  4. СЛЕВА ПРИСОЕДИНЯЙТЕСЬ к своей таблице данных, основываясь на части даты и времени:

       SELECT DATE(x.dt) AS dt,
              COALESCE(SUM(e.value), 0) AS sum_value
         FROM (SELECT DATE_ADD('2010-01-01', INTERVAL n.id - 1 DAY) AS dt
                 FROM numbers n
                WHERE DATE_ADD('2010-01-01', INTERVAL n.id -1 DAY) <= '2010-03-01' ) x
    LEFT JOIN ENTRY e ON DATE(e.datetime) = x.dt
                     AND e.entryid = 85
     GROUP BY DATE(x.dt) 
    

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

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

...