Создание серии дат

Каков наилучший способ в mysql генерировать ряд дат в заданном диапазоне?

Приложение, которое я имею в виду, это написать запрос отчета, который возвращает строку для каждой даты, независимо от того, есть ли какие-либо данные для отчета. В простейшей форме:

select dates.date, sum(sales.amount)
from <series of dates between X and Y> dates
left join sales on date(sales.created) = dates.date
group by 1

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

Ответ 1

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

Я нашел эту статью с тем, что кажется хорошим примером.

Ответ 2

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

select * from 
(select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) gen_date from
 (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
 (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
 (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
 (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
 (select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where gen_date between '2017-01-01' and '2017-12-31'

Ответ 3

Вы можете использовать серию дат переменной:

Set @i:=0;
SELECT DATE(DATE_ADD(X, 
INTERVAL @i:[email protected]+1 DAY) ) AS datesSeries
FROM yourtable, (SELECT @i:=0) r
where @i < DATEDIFF(now(), date Y) 
;

Не уверен, что это то, что вы пробовали:).

Следующее использование выше сгенерированного запроса в виде таблицы в left join:

set @i:=0;

select
d.dates,
sum(s.amount) as TotalAmount
from(
SELECT DATE(DATE_ADD(X, 
INTERVAL @i:[email protected]+1 DAY) ) AS dateSeries
FROM Sales, (SELECT @i:=0) r
where @i < DATEDIFF(now(), date Y) 
) dates d 
left join Sales s
on Date(s.Created) = Date(d.dateSeries)
group by 1
;

Ответ 4

Вы также можете использовать временную таблицу для создания серии дат. Проверьте ниже запрос:

CREATE TEMPORARY TABLE daterange (dte DATE); 

SET @counter := -1;
WHILE (@counter < DATEDIFF(DATE(_todate), DATE(_fromdate))) DO 
    INSERT daterange VALUES (DATE_ADD(_fromdate, INTERVAL @counter:[email protected] + 1 DAY));
END WHILE;

SELECT dates.dte, SUM(sales.amount)
FROM daterange dates
LEFT JOIN sales ON DATE(sales.created) = dates.date
GROUP BY dates.dte;