2012-12-31 95 views
16

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 

我试图创建一个有很多日期的表,但这似乎是一个糟糕的解决方法。

回答

15

我认为有一个万年历表是个好主意;您可以获得大量报告和查询功能,特别是在填充稀疏数据范围时。我发现this article似乎是一个很好的例子。

7

你可以使用一个变量产生枣系列:

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 
; 
+0

@Bohemian这是一个快鱼吃钓;)我太需要一个更多帽子:d – bonCodigo

+0

哪个帽子是你想获得? – Bohemian

+0

@Bohemian **江南Style **和**他在哪里?**欢迎您提出我的任何疑问或真棒答案;)blimey!哈哈哈,但它* lamer *等待一年:P – bonCodigo

5

您还可以使用临时表来生成日期序列。检查下面的查询:

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; 
6

如果你像我这样的情况:创建临时表被禁止是,和设置变量,也不允许,但你要生成日期列表中一个特定时期,说当年做一些聚集,使用此

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'