选择两个日期之间的日期的SQL查询

443

我有一个start_dateend_date。我想要得到这两个日期之间的日期列表。有人可以帮我指出查询中的错误吗?

select Date,TotalAllowance 
from Calculation 
where EmployeeId=1
  and Date between 2011/02/25 and 2011/02/27

这里的Date是一个datetime变量。


“Date”是大多数SQL标准中的保留字或关键字。你是如何避免它的限制的?^^ - bonCodigo
25个回答

676

你应该像这样用单引号将这两个日期括起来...

select Date, TotalAllowance from Calculation where EmployeeId = 1
             and Date between '2011/02/25' and '2011/02/27'

或者可以使用

select Date, TotalAllowance from Calculation where EmployeeId = 1
             and Date >= '2011/02/25' and Date <= '2011/02/27'

请记住,第一个日期是包含的,但第二个日期是不包含的,因为它实际上是“2011/02/27 00:00:00”


49
SQL Server将没有时间的日期默认为00:00:00。这个查询会不会返回2011/02/25和2011/02/26的午夜时刻? - Matt
6
@Deepak,你的第二部分应该说 >= 和 <=。 - IndoKnight
7
BETWEEN函数中的顺序很重要,左侧必须是最早的日期,右侧必须是最近的日期。这一点与SQL中的比较运算符“=”不同,在WHERE子句中,“EmployeeId = 1”和“1 = EmployeeId”均可使用。请注意不改变原意。 - Fi Horan
1
@Matt,根据between的文档,如果一行数据只有日期2011/02/27而没有时间,那么这一行数据相当于日期为2011/02/27 00:00,并且会在查询中返回,因为它小于或等于2011/02/27 00:00。所以如果你不需要处理时间,between应该可以按预期工作。 - timctran
2
@timctran 对的,但是2011/02/27 00:00是我们所说的2011/02/26的午夜。据推测,该查询意味着将27日包含在结果集中 - 但是一个时间戳为2011/02/27 5:00的条目将不会被包括在内。 - Sinjai
显示剩余3条评论

173

如果没有指定时间段,日期时间将会有一个值为date 00:00:00.000。所以,如果你想确保在你的范围内获取所有的日期,你必须为结束日期提供时间或者增加结束日期,使用<符号。

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date between '2011/02/25' and '2011/02/27 23:59:59.999'

或者

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date >= '2011/02/25' and Date < '2011/02/28'
select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date >= '2011/02/25' and Date <= '2011/02/27 23:59:59.999'

请勿使用以下代码,因为它可能会返回2011/02/28的记录,假如它们的时间是00:00:00.000。

select Date,TotalAllowance from Calculation where EmployeeId=1 
and Date between '2011/02/25' and '2011/02/28'

47
即使这些问题和答案最初是一段时间前提出的,人们仍然会查看它们。我来寻找答案,但我在这里看到的大部分内容都不完整或绝对不正确。我的回答可能无法帮助原始发帖者,但它可能有助于某个人,甚至可能是三年后的某个人。 - WelshDragon
4
@WelshDragon,你的回答非常有帮助。其他的回答中都没有提到日期格式在服务器上需要使用“简单日期”才能忽略小时数的事实。“<= END_DATE”假定为12点,而我不知道这一点。 我正在执行一个查询,“... <= 01/01/2014”,我无法理解为什么那天的订单没有显示出来。非常感谢你。 - Keith
1
今天尝试了一下,你也可以使用convert(date, Date) between '2011/02/25' and '2011/02/27'(至少在最近的MS SQL Server中)。 convert()部分将负责剥离时间部分,然后between比较将按预期工作。 - sensei
2
不要使用Date >= '2011/02/25' and Date <= '2011/02/27 23:59:59.999'或者between版本,这两种方式都是错误的,会返回值为'2011-02-28T00:00:00'的记录。也不要过于倾向于使用魔法时间23:59.59.997,虽然它更可靠,但仅适用于datetime列。Datetime2可以具有更高的精度,因此这种比较并不是你想要进入的习惯。相反,请使用Date >= '2011-02-25T00:00:00' and Date < '2011-02-28T00:00:00',这种方法没有任何缺点。 - Richard Abey-Nesbit
1
@RichardAbey-Nesbit WelshDragon在这里已经好几年没出现了 - 您能否编辑此答案以符合您的评论? - Andrew Morton
显示剩余5条评论

21

试试这个:

select Date,TotalAllowance from Calculation where EmployeeId=1
             and [Date] between '2011/02/25' and '2011/02/27'

日期值需要以字符串形式输入。

为确保您的查询在 SQL Server 2008 及更高版本中具有未来可用性,应该转义日期,因为它是稍后版本中的保留字。

请注意,没有时间的日期会将午夜作为默认值,因此您可能无法获得正确的值。


1
日期不是关键字,也不需要转义。语法高亮只是语法高亮,只有在关键字导致语法错误时才需要转义。使用显式转换而不是隐式转换日期字符串常量也是一个好习惯。-和日期之间的查询应该使用CAST('2011/02/25'AS DATETIME)和CAST('2011/02/27'AS DATETIME)。 - tponthieux
5
如果这是标记为SQL Server 2005的话,你说得对。然而,在2008版本及以上,Date是保留字,因此为了未来考虑,进行转义是没有坏处的。我已经编辑了我的答案。 - user114600
1
如果他为两个日期都指定了相同的日期,那么将返回零行,但我猜这不是运算符的要求。 - Zo Has

18
select * from table_name where col_Date between '2011/02/25' 
AND DATEADD(s,-1,DATEADD(d,1,'2011/02/27'))

在这里,首先需要将当前的endDate增加一天,得到的值是2011-02-28 00:00:00,然后你再减去一秒钟,将结束日期变成2011-02-27 23:59:59。这样做可以获取给定时间区间内的所有日期。

output:
2011/02/25
2011/02/26
2011/02/27

9
select * from test 
     where CAST(AddTime as datetime) between '2013/4/4' and '2014/4/4'

-- 如果数据类型不同


7
这段话虽然有些老旧,但是基于我在处理日期方面的丰富经验,你可能需要考虑这一点:不同的地区设置了不同的时间格式。所以有些人(还有一些数据库/计算机,取决于地区设置)可能会将这个日期11/12/2016读作2016年12月11日或者2016年11月12日。更甚的是,向MySQL数据库提供16/11/12会被内部转换为2016年11月12日,而运行在英国地区设置电脑上的Access数据库将其解释并保存为2012年11月16日。因此,我制定了明确的策略,每当我与日期和数据库打交道时,我总是遵循以下规则来编写我的查询和编程代码:
SELECT FirstName FROM Students WHERE DoB >= '11 Dec 2016';

请注意,Access也将接受#,因此:

SELECT FirstName FROM Students WHERE DoB >= #11 Dec 2016#;

但是MS SQL服务器不行,所以我总是像上面那样使用“ '”,这两个数据库都可以接受。

当从代码中的变量获取该日期时,我总是将结果转换为字符串,如下所示:

"SELECT FirstName FROM Students WHERE DoB >= " & myDate.ToString("d MMM yyyy")

我写这篇文章是因为我知道有时候一些程序员可能不够敏锐,无法检测到固有的转换。对于小于13的日期,不会出现错误,只会得到不同的结果!
至于所提出的问题,只需将最后一个日期加一天,并进行以下比较:
dated >= '11 Nov 2016' AND dated < '15 Nov 2016' 

您的信息帮助我完成了我的任务。我已经花费了超过10个小时来尝试解决问题,但是没有一个答案适用于我。当我按照您展示的方式连接字符串时,我的项目非常出色。但规则似乎不允许像这样编写SQL语句。每当我尝试将SqlCommand设置为添加日期参数到SQL语句中时,参数就无法绑定,我会收到“必须声明”@ startDate“和”@ endDate“的错误提示。我无法解决这个问题。我尝试了您的日期格式“dd MMM yyyy”,它可以正常工作,我还尝试了“yyyy MMM dd”,也执行了相同的操作。 - Dave Hampel
太好了,它有所帮助!上面是代码示例。为避免 SQL 注入,最好声明和使用参数。而且看起来你的项目已经要求/受到保护,这很好。 - Hannington Mambo

7

这个查询用于获取当前日期和其后三个日期之间的值。

SELECT * FROM tableName  WHERE columName 
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)

这将最终给当前日期增加额外的3天缓冲时间。

6
select Date,TotalAllowance 
from Calculation 
where EmployeeId=1
  and convert(varchar(10),Date,111) between '2011/02/25' and '2011/02/27'

6

尝试在# #之间输入日期,例如:

#2013/4/4# and #2013/4/20#

这对我很有帮助。


2
在这个上下文中,# 是什么意思? - B.K.
@B.K. 是一个分隔符,就像字符串的引号一样。例如,在向 SQL 语句提供值时,例如作为查询条件,它们的数据类型必须由“限定符”正确定义。这是通过将值夹在一对适当的字符之间来完成的。参考 --> 链接 - Aleksandar
1
@B.K. 如果这是TSql语法,您需要使用单引号(')才能得到您需要的内容。 参考资料 - Aleksandar
1
很明显这个问题是关于SQL Server和T-SQL的。T-SQL和SQL Server不接受在哈希标签之间的日期,而是接受在单引号之间的日期。这个答案是错误的。 - TT.
1
@TT。点赞数表明它仍然对某人有所帮助。在我写答案的时候,已经选择了采纳的答案。尽管如此,我写下这个答案是为了帮助任何可能从谷歌或其他地方来到这里的人 :) - Aleksandar

4
SELECT CITY, COUNT(EID) OCCURENCES FROM EMP 
WHERE DOB BETWEEN '31-JAN-1900' AND '31-JAN-2900' 
GROUP BY CITY 
HAVING COUNT(EID) > 2;

此查询将查找城市中出现次数超过2次并且出生日期在指定时间范围内的员工。


不太确定这与OP有什么关系。你能详细说明一下吗? - theking2
这是对问题的真正回答。问题是如何使用between以及他的查询有什么问题,问题在于使用单引号或双引号而不是将子句分成两个部分。 - Sonja

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