MySQL的“ between”子句不包括在内?


142

如果我运行带有between子句的查询,它似乎排除了结束值。
例如:

select * from person where dob between '2011-01-01' and '2011-01-31'

dob从'2011-01-01'到'2011-01-30'的所有结果;跳过dob“ 2011-01-31” 所在的记录。谁能解释这个查询的行为方式,以及如何修改它以包含dob“ 2011-01-31” 所在的记录?(由于用户选择了结束日期,因此未在结束日期前加上1。)


不。我的MySQL安装(版本?)BETWEEN包含两个值。我MySQL Server 5.7在Windows 10
绿色

Answers:


181

该字段dob可能具有时间成分。

截断它:

select * from person 
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'

59
代替CAST(dob AS DATE)您可以使用更简洁DATE(dob)
jkndrkn 2011年

11
在此过程中,使用>=<代替会获得更好的性能between
David Harkness 2012年

112
使用将获得更好的性能dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59。这是因为DATE(dob)必须为每一行计算一个值,并且不能在该字段上使用任何索引。
joshuahedlund

2
@joshuahedlund请为此解决方案添加答案。CAST效率不高。
doc_id

3
@joshuahedlund一直有效,直到您获得具有时间的数据为止t > 23:59:59 and t < 24:00:00。为什么要处理BETWEEN所有指定不当的问题?而是遵循David的建议和使用:WHERE dob >= '2011-01-01' AND dob < '2011-02-01'。最佳性能,并且每次都有效。
幻灭了

300

MySQL手册

这等效于表达式(min <= expr AND expr <= max)


3
此答案中的链接手册表明,比较DATE和DATETIME对象时,首选转换。因此,我猜@tiagoinu在最严格的意义上拥有最完整的答案,但两者都可以找到。
Kingsolmn 2013年

@jemminger可能是因为答案是从竞争对手 -postgres家伙:P
nawfal

27
简而言之,两者之间是包容性的 ...这就是为什么这个答案令人震惊。
拉斐尔

6
旧评论,但我想将此与特定查询联系起来。“ BETWEEN”包括在内,但没有指定时间的日期应填充到00:00:00。因此,比较日期范围将丢失最后一天。调用DATE(dob)或指定一天的结束时间。
wintermute92 2013年

他们说实践是黄金,从我的用例来看,它根本不是包容性的,我想知道为什么会发生这种情况。我尝试过,有时它有时不起作用。在TIME数据字段上使用它。
Jeffery ThaGintoki

99

问题是2011-01-31确实是2011-01-31 00:00:00。那是一天的开始。白天的一切都不包括在内。


19
这确实可以解释发生了什么并回答了问题。
Ivan P

3
这些年来,这个答案仍然是最好的。非常感谢。
Strabek '17

31
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'

1
认为值得注意的是,这将不包括日期,2011-01-31 23:59:59但将包括直到2011-01-31 23:59:58 一天的最后一秒的日期,这可能很小,但是会有人从中受益。
doc_id 2015年

1
MySQL文档中的rahmanisback由于BETWEEN双向包含,因此我可以确认将包括最后一秒。参考dev.mysql.com/doc/refman/5.5/en/...
Felype

1
是的,@ Felype你是对的。我自己在mysql数据库中检查了这个。23:59:59结果中也包括。因此,这两种方式都具有包容性。
2016年

2
如果该dob列是具有亚秒精度的时间戳,那么BETWEEN除非使用'2011-02-01 00:00:00'代替,否则仍不会错过当天最后一秒内的事件吗?
氮气

1
-1。不会包含2011-01-31 23:59:59.003。@氮气使用2011-02-01 000:00:00将在2月1日错误地包含零时间...。这就是原因>=<应改为使用。
幻灭了

6

您在查询中引用的字段是Date类型还是DateTime类型?

您描述的行为的一个常见原因是,当您使用DateTime类型时,实际上应该使用Date类型。也就是说,除非您真的需要知道某人的出生时间,否则只需使用Date类型。

结果中不包含最后一天的原因是查询采用的方式是假设查询中未指定日期的时间部分。

也就是说:您的查询被解释为2011年1月30日至2011年1月31日之间的午夜,但数据可能在2011年1月31日这一天的某个时候值。

建议:如果该字段是DateTime类型,则将其更改为Date类型。


4

您好,此查询对我有用,

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

2
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'

令人惊讶的是,这样的转换是MySQL中许多问题的解决方案。


10
令人惊讶的是,这正是公认的答案(和其他几个答案)所说的……比您早两年。
克里斯·贝克

0

将最高日期设置为date + 1 day,因此,根据您的情况,将其设置为2011-02-01。


1
这将错误地包括2月1日的零时间BETWEEN。但>=<应改为使用。
幻灭了

0

您可以通过以下方式运行查询:

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

就像其他人指出的那样,如果您的日期是硬编码的。

另一方面,如果日期在另一个表中,则可以添加一天并减去一天(如果保存的日期没有秒/时间),例如:

select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)

避免对dob字段进行强制转换(例如在接受的答案中),因为这可能会导致巨大的性能问题(例如dob,假设存在一个无法在字段中使用索引)。执行计划可能会改变从using index conditionusing where,如果你做的东西像DATE(dob)或者CAST(dob AS DATE),所以一定要小心!


0

在MySql中,值之间包含所有值,因此当您尝试在“ 2011-01-01”和“ 2011-01-31”之间获取时

它会包含2011-01-01 00:00:00从上到下,2011-01-31 00:00:00 因此在2011-01-31中实际上没有任何内容,因为它的时间应该从2011-01-31 00:00:00 ~ 2011-01-31 23:59:59

对于上限,您可以更改为2011-02-01然后它将获取所有数据2011-01-31 23:59:59

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.