Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: MySQL: запрос на выборку диапазона дат из таблицы включая пустые строки  (Прочитано 13320 раз)
0 Пользователей и 1 Гость смотрят эту тему.
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« : 25-08-2010 16:34 » 

MySQL 5.x
Предусловие: есть таблица с, например, временем, залогированным пользователями.
Нас интересуют 2 поля - дата и время.
Задача: Необходимо выбрать сумму залогированного времени с группировкой по дням.
В общем, задача решается запросом ниже, но если за какой-то день не было записей, то эта строчка будет пропущена.
Хочется все равно иметь там 0 и дату.
Условие: писать в таблицы нельзя, создавать таблицы нельзя. Права только на чтение.
Код: (SQL)
SELECT format((ifnull(SUM(wl.timeworked), 0) div 60)/60, 2) daylogged, DATE(wl.updated) ldate
FROM worklog wl
WHERE wl.author='username' AND wl.updated BETWEEN '2010-08-21 00:00:00' AND '2010-08-25 23:59:59'
GROUP BY DATE(wl.updated)

Можно сделать, конечно, несколько запросов и вычислять пропущенные даты на клиенте, но это не так красиво. Кто может подсказать?
Понятие 'calendar tables' как оно показано тут, скорее всего, не подойдет, поскольку нельзя гарантировать, что даже в других таблицах есть диапазон индексов идущих подряд (чтоб использовать для фейковой таблицы и группировки по ним).
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 25-08-2010 18:22 » 

Для создания последовательности без пропусков можно взять за основу такой код:

Код:
SET @n = 0;
SELECT seq.num
  FROM (
    SELECT @n := @n + 1 num
    FROM some_table
  ) seq
  WHERE seq.num < 100;

Для его выполнения нужна любая таблица с числом строк не меньше требуемой длины последовательности. Но не слишком длинная, иначе будет медленно выполняться. На тесте у меня таблица 100 тыс. строк, время выполнения запроса - 0.07 сек.
Либо заранее иметь таблицу с полем последовательности - это оптимальнее всего.

Последовательность нужно преобразовать в даты:

Код:
SET @n = 0;
SELECT '2010-08-01' + INTERVAL (seq.num - 1) DAY `date`
  FROM (
    SELECT @n := @n + 1 num
    FROM some_table
  ) seq
  WHERE seq.num < 100;

Потом внешним объединением подключить группируемую таблицу.



Попробовал с LIMIT в подзапросе - получилось мгновенно. Упрощаем до одного запроса, внеся инициализацию @n внутрь.

Код:
SELECT '2010-08-01' + INTERVAL seq.num DAY `date`
  FROM (
    SELECT @n := 0 num
    UNION
    SELECT @n := @n + 1 num
    FROM some_table
    LIMIT 100
  ) seq
  WHERE seq.num BETWEEN 0 AND 30;
« Последнее редактирование: 25-08-2010 18:30 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #2 : 26-08-2010 15:15 » 

RXL, спасибо, отлично работает!
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines