Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Группировка по дням в диапазоне / 12 сообщений из 12, страница 1 из 1
03.02.2016, 10:39
    #39161686
Oldwin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Всем привет, у меня есть таблица:

table1
- id
- (int) status
- (int) quantity (количество чего-то в промежуток времени)
- (date) start (начальная дата)
- (date) end (конечная дата)

Я создал вспомогательную таблицу для выборки по дням
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
DROP PROCEDURE IF EXISTS filldates;
DELIMITER |
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)
BEGIN
  WHILE dateStart <= dateEnd DO
    INSERT INTO helper_days (_day) VALUES (dateStart);
    SET dateStart = date_add(dateStart, INTERVAL 1 DAY);
  END WHILE;
END;
|
DELIMITER ;
CALL filldates('1970-01-01','2038-01-01');



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

Выбираю все даты в диапазоне:
Код: sql
1.
2.
3.
SELECT `_day`
FROM `helper_days`
WHERE (`_day` BETWEEN '2016-02-01' AND '2016-03-01')



Группирую данные по статусу для конкретного дня
Код: sql
1.
2.
3.
4.
SELECT `unit`, `status`, SUM(`quantity`) as `quantity`
FROM `table1` 
WHERE ('2016-02-11' BETWEEN `start` AND `end`)
GROUP BY `unit`, `status, `quantity`



Вопрос: как вот этот конкретный день '2016-02-11' заменить на мою вспомогательную таблицу? Т.е. чтоб был вывод по всем дням в диапазоне. Или может вообще вспомогательная таблица не нужна и я куда-то не в те дебри зашел.
Большое спасибо за помощь.
...
Рейтинг: 0 / 0
03.02.2016, 10:44
    #39161694
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Знаете, было бы более разумно формулировать исходную задачу, а не свои попытки её решить. Причём сформулировать её точно и однозначно, чтобы не возникало дополнительных вопросов.
...
Рейтинг: 0 / 0
03.02.2016, 11:22
    #39161726
Oldwin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Akina, из таблицы table1 сгруппировать данные по дням (сумму столбца quantity) + status
При этом таблица имеет структуру, описанную выше начальная дата, конечная, количество
Код: sql
1.
SELECT `unit` , `status` , `quantity` , `start` , `end` 


Код: sql
1.
2.
3.
4.
5.
unit  status quantity           start             end
3 	2 	1 	     2016-02-02 	2016-02-12
3 	2 	1 	     2016-01-16 	2016-02-24
4 	1 	2 	     2016-02-16 	2016-02-26
7 	1 	1 	     2016-02-09 	2016-02-12



Это резервирование какого-то количества товара в промежуток дат. Нужно вывести для каждого дня в определенном диапазоне сколько в этот день зарезервировано unit с каким status

Конечный вид, какой-то такой:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
day                unit      status   quantity
......
2016-01-02      3         2          2
2016-01-03      3         2          2
.....
2016-01-13      3         2          1
......
2016-01-16      4         1          2
...
Рейтинг: 0 / 0
03.02.2016, 11:51
    #39161756
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Oldwin, какой должен быть результат, если:
-в день икс не будет вообще ни одного юнита?
-в день игрек по как минимум одному из статусов не будет ни одного юнита?
...
Рейтинг: 0 / 0
03.02.2016, 12:02
    #39161774
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Если я верно понимаю, то группа (`unit`, `status`, `quantity`) уникальна в пределах таблицы, так?
Тогда подход с формированием опорной таблицы вполне правильный. Единственное разве - не убеждён, что есть смысл создавать такую таблицу статической, да ещё на такой диапазон дат, я бы пошёл по пути получения нужных данных в хранимой процедуре, где создавал и заполнял бы таблицу дат только в нужном диапазоне по аналогии с вышеприведённым кодом (CREATE TEMPORARY TABLE dates () ENGINE=MEMORY) - во-первых, она компактная, без "лишних" данных, во-вторых, быстрая, в третьих, не надо заботиться об очистке.
Ну а сам запрос при этом тривиален, типа:
Код: sql
1.
2.
3.
4.
SELECT dates.dat, t1.unit, t1.status, SUM(t1.quantity) as quantity
FROM dates, table1 t1
WHERE dates.dat BETWEEN t1.start AND t1.end
GROUP BY dates.dat, t1.unit, t1.status
...
Рейтинг: 0 / 0
03.02.2016, 12:25
    #39161826
Oldwin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
tanglir ,
Правильные вопросы, спасибо.
автор-в день икс не будет вообще ни одного юнита?

0
автор-в день игрек по как минимум одному из статусов не будет ни одного юнита?
не выводить ничего с этим статусом.
Можно даже упростить задачу и выбирать только WHERE status = 2. Это не принципиально и я сам допишу, чтоб не нагружать уважаемых форумчан, у меня проблема с выборкой по каждому дню в диапазоне и комбинации дат.


Akina ,
авторЕсли я верно понимаю, то группа (`unit`, `status`, `quantity`) уникальна в пределах таблицы, так?
Нет. Допустим у нас есть unit #3 (это его id). Его много (допустим 100 штук, это не важно и хранится в другой таблице).
Когда резервируется этот юнит #3 количеством 5 шт. в таблицу добавляется строка
Код: sql
1.
2.
unit  status quantity           start             end
3 	2 	5 	     2016-02-02 	2016-02-12


3 - юнит №3
2 - ID статуса
5 - количество (может быть любым числом)
Начальная и конечная дата.

Таких записей в данной таблице может быть неопределенное количество. Они указывают лишь диапазон в котором есть аренда данного юнита и его количество.
При этом тот же юнит может быть в разных комбинациях количества в разные промежутки арендован. Где-то на один день, где-то на несколько. И все эти пересечения в разный день дают различное количество.
Для конкретного дня его можно найти запросом, который я написал в первом сообщении, группировкой SUM(`quantity`)
Код: sql
1.
WHERE ({:дата:} BETWEEN `start` AND `end`)


Вот как вот в эту {:дата:} подставить массив из необходимых дат (диапазон), чтоб не где-то в скрипте перебирать все даты, а получить один запрос.
...
Рейтинг: 0 / 0
03.02.2016, 12:46
    #39161867
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
OldwinПравильные вопросы, спасибо.
автор-в день икс не будет вообще ни одного юнита?

0а статус тут какой должен быть?

В принципе, задача-то простейшая: суммируем quantity с группировкой по date,status,unit, полученный результат left join-им или просто join-им к опорной таблице дат. Вопрос только в деталях отображения.
...
Рейтинг: 0 / 0
03.02.2016, 12:47
    #39161869
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Oldwin , это я перестарался. Тут неуникальность никак не влияет на итог, не обращай на это внимания. Ведь таблицу опорных дат ты создаёшь сам, и в ней дубликатов не будет.

Oldwinполучить один запрос.
Ну собсно так оно и есть. Только не запрос, а ХП... но в ней - один запрос на получение данных за все даты сразу. А т.к. создание и заполнение опорной таблицы диск не трогает, то временем на эти операции в первом приближении можно и пренебречь - вряд ли тебе потребуется генерация отчёта за сотню лет...
...
Рейтинг: 0 / 0
03.02.2016, 12:48
    #39161872
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
OldwinВот как вот в эту {:дата:} подставить массив из необходимых дат (диапазон), чтоб не где-то в скрипте перебирать все даты, а получить один запрос.

Код: sql
1.
2.
from base_dates bd
join mytable mt on bd.dt between mt.start and mt.end

ну или не битвин, а 2 неравенства, если там не интервалы, а (полу)отрезки.
...
Рейтинг: 0 / 0
03.02.2016, 13:44
    #39161948
Oldwin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
tanglir ,

Действительно, это же JOIN простой, спасибо ) Как-то так стало получаться:

Код: sql
1.
2.
3.
4.
5.
SELECT `_day`, `unit`, `status`, SUM(`quantity`) AS `quantity`
FROM `helper_days` AS dt
JOIN `table1` AS book  ON `dt`.`_day`  BETWEEN `book`.`start` AND `book`.`end`
WHERE `_day` BETWEEN '2016-01-01' AND '2016-03-01'
GROUP BY `_day`, `unit`, `status`, `quantity`



Akina , спасибо за подсказку с временной таблицей, но ее придется создавать каждый раз, а запросов таких много предполагается. Я так понимаю, самый оптимальный путь - хранить в памяти таблицу с датами? Она весит для всех нужных дат не много.
...
Рейтинг: 0 / 0
03.02.2016, 13:46
    #39161951
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Oldwinхранить в памяти таблицу с датами?Зачем в памяти, создайте (и заполните) её в БД. Это и сделать-то надо ровно один раз.
...
Рейтинг: 0 / 0
03.02.2016, 14:36
    #39162028
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Группировка по дням в диапазоне
Oldwinее придется создавать каждый раз, а запросов таких много предполагается
Создание компактной временной таблицы на MEMORY движке выполнится ГОРАЗДО быстрее, чем чтение статической таблицы с диска, да ещё минус одно условие во WHERE.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Группировка по дням в диапазоне / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]