如何在mysql查询语句中获取两个日期之间的日期列表

52

我想通过select查询获取两个日期之间的日期列表。例如:

如果我提供 '2012-02-10' 和 '2012-02-15',我需要结果。

date      
----------
2012-02-10
2012-02-11
2012-02-12
2012-02-13
2012-02-14
2012-02-15 

我怎样可以获取?


下面的两个答案都是正确的,但似乎不是你想要的。你能提供更多信息吗? - James
我只想要在两个日期之间的日期列表。这些日期不在我的表中,我只是想问是否有像SELECT CURRENT_DATE()这样可以获取当前日期的函数(不需要指定表)。或者我们还有其他方法可以获得两个日期之间的日期吗?@Mark Byers的答案是正确的,但必须添加另一个具有大量数据的表。如果有其他解决方案,那就看看吧。 - Sangeetha Krishnan
@SangeethaKrishnan 我不确定在MySQL/SQL中完成这个任务是最好的答案。你是要直接在数据库中使用它,还是为了使用其他语言(如PHP/C#)编写的程序? - James
如果你需要在数据库中完成这个任务,tsabz的回答应该是你需要的。 - James
6个回答

151

尝试:

select * from 
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date from
 (select 0 i 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 i 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 i 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 i 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 i 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 selected_date between '2012-02-10' and '2012-02-15'

-可处理将近未来300年的日期范围。

[在UrvishAtSynapse的建议编辑后进行了更正。]


1
在所有回答中,以及相关问题的所有回答中,这个解决方案是最简单和最好的。不需要存储过程,只需从此输出创建一个表即可。干得好@MarkBannister - s2t2
19
如果您能解释一下这个问题,我会非常感激。 - Rahul Prasad
10
Rahul,这将通过将每个数字组合在一起(00000、00001、... 99999)生成10万行内容。每行的列被转换为一个单独的数字,再加上日期“1970-01-01”,得到10万个日期,每行一个,然后进行筛选。为提高效率,可以从所需日期开始(而非1970-01-01),将其转换成“<=”,最后将数量级缩小到所需大小。如果只需要20个日期,则只需使用100或t0与t1相结合即可。 - Gerard ONeill
或许是一个小细节:但是在 select 0 i union select 1 union ... 中的每个 union 应该改为 union all - Paul Maxwell
2
并不完全正确,“union all” 不会为了唯一性扫描结果集,“union distinct” 会这么做。在这个例子中,性能差异微不足道,但作为最佳实践的示例,它确实很重要(我认为)。 - Paul Maxwell
显示剩余2条评论

23
set @i = -1;
SELECT DATE(ADDDATE('2012-02-10', INTERVAL @i:=@i+1 DAY)) AS date FROM `table`
HAVING 
@i < DATEDIFF('2012-02-15', '2012-02-10') 

这将精确地返回您预期的结果集。此查询仅需要您更改datediff和adddate中的两个不同日期。


1
我还必须提到,table 不需要包含任何日期行,但是 SQL 查询只需要存在 FROM。table 可以是您数据库中的任何表。 - hexparrot
我尝试使用类似于你的嵌套查询生成的日期来选择日期。参考sqlfiddle,但出于某种原因,查询没有返回任何结果。请问您打算如何使用您的查询生成的这些值? - bonCodigo
1
查询没有显示超过4条记录..日期列总是显示4条记录...我尝试更改datediff函数的日期.. - Ankit Sharma
如果我没有日期,而是有起始和结束计数器(如时间戳),似乎无法正常工作:SELECT start + @i:=@i+1 AS counter FROM table HAVING @i < end-start。End和Start是表中每行的值,我想将它们之间的值扩展开。 - giordano
9
方案不错,但存在一个令人失望的问题。 您在选择(select)中声明的表格应该具有更多或等于您希望选择的行数。 因此,如果您想要获取一整年的日期,而您的表格只有100行,您将只获得前100行。 这就是为什么我更喜欢这个解决方案https://dev59.com/r4Xca4cB1Zd3GeqPFj5b#33411681。 - maks1m
2
这个查询只会列出与 table 中记录数相同的结果 - 这对于记录集很大且结果数始终小于记录数的情况是可以的,但如果您尝试检索比表中记录数更多的数据,则无法正常工作。 - SteJ

16

对我来说,所接受的答案在MySQL 5.5中不起作用。我更新了查询以使其对我有效:

select * from 
(select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) selected_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 selected_date between '2012-02-10' and '2012-02-15'

2
这个方法可以完成任务,但如果你觉得它有点慢,而且你只需要未来的日期,那么请将'1970-01-01'替换为CURDATE() - 在我的情况下,通过减少adddate调用的结果行数,执行时间减少了一半。 - totallyNotLizards

1

3
为什么是-1?这个过程有点复杂,但非常高效,他可以通过它精确地得到他需要的结果。 - BMN
1
我给了它一个加一,至少把它带回到0。我刚刚发布了相同的帖子,然后发现你已经发过了。这是他们需要的。 - James
1
为什么使用存储过程,当明显不需要使用它呢? - hexparrot

0

您可以创建一个包含您可能需要使用的所有日期的表:

date
2000-01-01
2000-01-02
2000-01-03
...etc..
2100-12-30
2100-12-31

然后按以下方式查询该表:

SELECT date
FROM dates
WHERE date BETWEEN '2012-02-10' AND '2012-02-15'

谢谢您的回复。除了存储这么多数据外,还有其他方法吗? - Sangeetha Krishnan
@SangeethaKrishnan:如果你仔细想想,其实这并不是很多的数据。100年的日期只有大约36500条记录——在服务器上几乎不需要存储空间。如果你担心性能问题,请确保该列已经建立索引。 - Mark Byers
4
最佳实践应该是不要存储可计算的数据。保存每个日期长达X年似乎非常不优雅。 - hexparrot
2
@hexparrot:同意,但是“最佳实践”在这里应该被更广泛地理解。如果OP想要一个便携式的日期解决方案,我真的不认为在单独的表中存储一系列日期会有很大的惩罚,尽管显然缺乏优雅,但通过将列索引化作为奖励。被接受的答案也相当便携,但由于MySQL不允许在视图中使用子查询,因此查询不能被存储为这样的查询。那么如果OP想要在多个查询中连接日期序列,你的“最佳实践”指南会是什么?存储过程? - VH-NZZ

-8
SELECT * FROM tablexxx WHERE datecol BETWEEN '2012-02-10' AND '2012-02-15';

1
谢谢您的回复。这些日期不在表格中。 - Sangeetha Krishnan
我希望它是通用的。这意味着像选择CURRENT_DATE()一样。 - Sangeetha Krishnan
5
我认为不应该允许匿名的踩票,尤其是没有解释的情况下。 - blankabout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接