167

我有一个这样的查询:

SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'

但这没有给出任何结果,即使有 1 日的数据。

created_at看起来2013-05-01 22:25:19,我怀疑它与时间有关?如何解决?

如果我做更大的日期范围,它工作得很好,但它也应该(包括)与单个日期一起工作。

4

9 回答 9

349

包容性的。您正在将日期时间与日期进行比较。当一天开始时,第二个日期被解释为午夜。

解决此问题的一种方法是:

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 有一篇关于日期的长博客文章(这里),在那里他讨论了这个和其他日期问题。

于 2013-05-02T21:03:37.473 回答
67

假设BETWEEN语法中的第二个日期引用被神奇地认为是“一天的结束”,但这是不正确的

即这是预期的:

从案例中选择 *
WHERE created_at BETWEEN '2013-05-01'的开头和'2013-05-01'的结尾

但真正发生的是:

从案例中选择 *
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确实包括范围内的下限值和上限值,但并没有神奇地将日期设为“开始”或“结束”。

BETWEEN按日期范围过滤时应避免使用。

始终使用>= AND <_

从案例中选择 *
WHERE (created_at >= '20130501' AND created_at < '20130502')

括号在这里是可选的,但在更复杂的查询中可能很重要。

于 2014-10-04T07:50:15.460 回答
19

您需要执行以下两个选项之一:

  1. between在您的情况中包括时间部分:(... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59'不推荐......见最后一段)
  2. 使用不等式代替between. 请注意,您必须将一天添加到第二个值:... where (created_at >= '2013-05-01' and created_at < '2013-05-02')

我个人的偏好是第二种选择。此外,Aaron Bertrand对为什么应该使用它有一个非常清楚的解释。

于 2013-05-02T21:05:54.320 回答
9

只需使用时间戳作为日期:

SELECT * FROM Cases WHERE date(created_at)='2013-05-01' 
于 2015-09-12T19:13:21.310 回答
7

我发现将日期时间字段与日期字段进行比较的最佳解决方案如下:

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 

这等效于包含介于之间的语句,因为它包括开始日期和结束日期以及介于两者之间的日期。

于 2015-09-24T15:54:42.150 回答
3
cast(created_at as date)

这仅适用于 2008 年和更新版本的 SQL Server

如果您使用的是旧版本,请使用

convert(varchar, created_at, 101)
于 2014-05-22T19:19:48.283 回答
2

您可以使用date()从日期时间中提取日期并将结果作为包含日期提供给您的函数:

SELECT * FROM Cases WHERE date(created_at)='2013-05-01' AND '2013-05-01'
于 2018-03-22T07:15:06.540 回答
1

你的代码

SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'

SQL如何读取它

SELECT * FROM Cases WHERE '2013-05-01 22:25:19' BETWEEN '2013-05-01 00:00:00' AND '2013-05-01 00:00:00'

如果您在比较 DateTime 和 Date 默认情况下不提及时间 hours:minutes:seconds 在您的情况下将为零日期是相同的,但如果您比较时间created_at22 hours于结束日期范围

如果上述内容很清楚,您可以通过多种方式解决此问题,例如将结束时间放在结束日期中,例如BETWEEN '2013-05-01' AND ''2013-05-01 23:59:59''

或者

只需将 create_at 转换为日期,就像cast(created_at as date)在转换为日期之后一样,'2013-05-01 22:25:19'将等于'2013-05-01 00:00:00'

于 2020-12-10T21:53:36.133 回答
0

sql查询之间的动态日期

var startDate = '2019-08-22';
var Enddate = '2019-10-22'
     let sql = "SELECT * FROM Cases WHERE created_at BETWEEN '?' AND '?'";
     const users = await mysql.query( sql, [startDate, Enddate]);
于 2019-11-22T07:25:21.187 回答