SQL“之间”不包括在内

Posted

技术标签:

【中文标题】SQL“之间”不包括在内【英文标题】:SQL "between" not inclusive 【发布时间】:2013-04-27 04:36:58 【问题描述】:

我有一个这样的查询:

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

但是即使1号有数据,这也没有结果。

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

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

【问题讨论】:

那么,1 和 1 之间有多少个数字? 1.5 应该在 1 和 1 之间吗? Just don't use BETWEEN for date/time ranges. Ever. 并且要小心你如何评估“工作正常”——你是否仔细检查了该范围内最后一天的结果?如果它们没有任何时间与它们相关联,您将只包括所有行。 更新了 Aaron 的 URL:sqlblog.org/2011/10/19/… 【参考方案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 时未提及时间,默认时时:分:秒在您的情况下将为零,日期相同,但如果您比较时间 created_at 是在结束日期范围之前的 22 hours

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

在转换为日期'2013-05-01 22:25:19' 之后将create_at 转换为cast(created_at as date) 这样的日期将等于'2013-05-01 00:00:00'

【讨论】:

【参考方案2】:

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]);

【讨论】:

【参考方案3】:

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

    between 条件中包含时间组件:... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59'(不推荐...见最后一段) 使用不等式代替between。请注意,您必须将一天添加到第二个值:... where (created_at >= '2013-05-01' and created_at < '2013-05-02')

我个人的偏好是第二个选项。另外,Aaron Bertrand 有 a very clear explanation on why 应该使用。

【讨论】:

+1 表示 2。但 -1 表示 1。这种结束一天的黑客攻击完全不可靠,而且是个坏主意。 @AaronBertrand 我也更喜欢选项 2(我经常使用它)。但是为什么你说选项 1“完全不可靠”呢? please read this in full。对于包含时间的日期范围查询,您永远不应该使用BETWEEN;太多可能会出错。 虽然 2. 有效,但我将始终将其写为 where ('2013-05-01' <= created_at and created_at <= '2013-05-01') 以提高可读性【参考方案4】:

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

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

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

【讨论】:

为了这个好答案的完整性,我建议使用dateadd 来获得第二天。 @TimLehner 为了得到一个好的答案,我会使用“20130501”的 ISO-8601 格式。对于使用 dateformat dmy 的非美国人,你会得到这个:set dateformat dmy;select month(cast('2013-05-01' as datetime)); =1 @RichardTheKiwi - 我相信 explicit 位正在使用一个在一端关闭的间隔 (&gt;=) 在另一端打开 (&lt;) 并结合检查一个指定结束日期之后的一天。 @scottb 就我个人而言,每次我想显示、导出、导入或编写带有日期时间的类时,我都会觉得很烦人。我认为 SQL Server 有很多内置功能可以在大多数情况下操作和比较日期时间。 您永远不应该在where 子句中强制转换列,因为它会丢失它拥有的任何索引。这是一个非常糟糕的模式。【参考方案5】:

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

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 

这相当于一个包含的 between 语句,因为它包括开始日期和结束日期以及介于两者之间的日期。

【讨论】:

【参考方案6】:

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

SELECT * FROM Cases WHERE date(created_at)='2013-05-01' AND '2013-05-01'

【讨论】:

【参考方案7】:

假设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

始终改用&gt;= AND &lt;

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

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

【讨论】:

在问题已经得到解答后,不确定发布此内容是否明智,但我想强调一点不同 致编辑;请不要尝试将伪 SQL 制作成代码块,因为注释依赖 BOLD,它根本不起作用。 请各位编辑(再次)不要通过伪代码添加虚假引号;他们不帮助理解。【参考方案8】:

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

SELECT * FROM Cases WHERE date(created_at)='2013-05-01' 

【讨论】:

问题标记为SQL Server,而'DATE' is not a recognized built-in function name.需要转换***.com/a/20973452/4233593 ? 它有效!!!!拯救我的一天?【参考方案9】:
cast(created_at as date)

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

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

convert(varchar, created_at, 101)

【讨论】:

convert(varchar, created_at, 101) 结果就像dd/MM/yyyy 并且OP的字符串是yyyy-MM-dd,我认为这个答案行不通;)。

以上是关于SQL“之间”不包括在内的主要内容,如果未能解决你的问题,请参考以下文章

SQL 'overlaps' 仅获取开始和结束之间的日期(不包括开始和结束日期)

SQL 之间不包括所有查询范围(日期)

sql语句 decimal(18,0)啥意思

SQL中有几种连接?有啥区别?(左连右连内连和外连?)

嵌套 SQL 语句但在内部语句中重用 out 变量?

SQL中 between and 包不包括两端值