SQL“之间”不包括在内
我有这样的查询:
SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'
但即使在1日有数据,也没有结果。
created_at
看起来像2013-05-01 22:25:19
,我怀疑它必须与时间? 这怎么解决?
它工作得很好,如果我做更大的date范围,但它应该(包括)工作与一个单一的date。
它是包容性的。 你正在比较date和date。 当一天开始时,第二个date被解释为午夜。
解决这个问题的一个方法是:
SELECT * FROM Cases WHERE cast(created_at as date) BETWEEN '2013-05-01' AND '2013-05-01'
解决这个问题的另一个方法是显式的二进制比较
SELECT * FROM Cases WHERE created_at >= '2013-05-01' AND created_at < '2013-05-02'
Aaron Bertrand在date( 这里 )有很长的博客文章,他在这里讨论这个和其他date问题。
假定BETWEEN
语法中的第二个date引用神奇地被认为是“一天结束”,但这是不真实的 。
即这是预期的:
SELECT * FROM个案 WHERE created_at'2013-05-01' 开始和 '2013-05-01' 结束
但真正发生的是这样的:
SELECT * FROM个案 WHERE created_at BETWEEN'2013-05-01 00:00:00 + 00000'AND'2013-05-01 00:00:00 + 00000 '
这成为相当于:
SELECT * FROM Cases WHERE created_at = '2013-05-01 00:00:00 + 00000 '
问题是关于BETWEEN
的观点/期望之一,其中包括范围内的较低值和较高值,但不奇怪地将“date”或“结束”作为date。
按date范围进行筛选时应避免使用BETWEEN
。
总是使用>= AND <
来代替
SELECT * FROM个案 WHERE(created_at > = '20130501'AND created_at < '20130502')
圆括号在这里是可选的,但在更复杂的查询中可能是重要的。
您需要执行以下两个选项之一:
- 包括时间组件在你的条件
between
:... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59'
(不build议…见最后一段) - 使用不等式而不是
between
。 注意,那么你将不得不增加一天到第二个值:... where (created_at >= '2013-05-01' and created_at < '2013-05-02')
我的个人喜好是第二种select。 另外, Aaron Bertrand对于为什么要使用这个问题有一个非常明确的解释 。
只需使用时间戳作为date:
SELECT * FROM Cases WHERE date(created_at)='2013-05-01'
我发现将date时间字段与date字段进行比较的最佳解决scheme如下所示:
DECLARE @StartDate DATE = '5/1/2013' ,@EndDate DATE = '5/1/2013' SELECT * FROM Cases WHERE DATEDIFF(DAY,created_at,@StartDate) <=0 AND DATEDIFF(DAY,created_at,@EndDate)>=0
这相当于一个包含性的声明,因为它包括开始和结束date以及其间的内容。
作为备选:
SELECT * FROM Cases WHERE convert(varchar, created_at, 120) Like '2013-05-01%'
cast(created_at as date)
这将只在2008年和更新版本的SQL Server工作
如果您使用的是旧版本,请使用
convert(varchar, created_at, 101)