【问题标题】:SQL Server : fetching records between two dates?SQL Server:获取两个日期之间的记录?
【发布时间】:2012-10-17 10:52:44
【问题描述】:

在 SQL 中,我编写了一个 SELECT 语句来获取两个日期之间的数据,使用 between and

例如:

select * 
from xxx 
where dates between '2012-10-26' and '2012-10-27'

但返回的行仅适用于 26 日,而不是 26 日和 27 日。

你能帮帮我吗?谢谢。

【问题讨论】:

  • 取决于您使用的 SQL Server 什么版本,以及您的dates 列是什么数据类型 ....
  • 另外:当您使用它时 - 我建议使用 safe 日期/时间格式 - 适用于所有 SQL Server 版本且独立于任何日期的格式、区域或语言设置。这将是 20121017 23:59:59.997YYYYMMDD没有破折号的日期!) - 或者然后是 2012-10-17T23:59:59.997(破折号在日期,和一个固定的 T 作为日期和时间部分之间的分隔符)
  • 我认为这个链接有助于解决你的问题:stackoverflow.com/questions/2462738/…

标签: sql-server datetime date-range


【解决方案1】:

您需要更加明确,并添加开始和结束时间,精确到毫秒:

select * 
from xxx 
where dates between '2012-10-26 00:00:00.000' and '2012-10-27 23:59:59.997'

数据库可以很好地将'2012-10-27'解释为'2012-10-27 00:00:00.000'

【讨论】:

  • 实际上,对于DATETIME 列,您需要指定..23:59:59.997,因为DATETIME 具有3ms 的分辨率精度。对于DATETIME2,您的解决方案确实可以正常工作。
  • 只要有足够的眼球,所有的问题都会变得肤浅 ... :-)
  • @marc 你的意思是反过来吗?它对 DATETIME2 不起作用。见select cast('20120101 12:34:56.9999999' as datetime2)
  • @RichardTheKiwi:是的 - Oded 最初有 ... 23:59:59.999,它适用于 DATETIME2(但不适用于 DATETIME
【解决方案2】:

试试这个:

select * 
from xxx 
where dates >= '2012-10-26 00:00:00.000' and dates <= '2012-10-27 23:59:59.997'

【讨论】:

  • 这将不会选择具有date2012-10-27 23:59:59.0032012-10-27 23:59:59.997 的行 - 在该日期范围内也可能有一些行!
【解决方案3】:

正如其他人回答的那样,您可能有一个 DATETIME(或其他变体)列,而不是 DATE 数据类型。

这是适用于所有人的条件,包括DATE

SELECT * 
FROM xxx 
WHERE dates >= '20121026' 
  AND dates <  '20121028'    --- one day after 
                             --- it is converted to '2012-10-28 00:00:00.000'
 ;

@Aaron Bertrand 已在以下博客中讨论此问题:What do BETWEEN and the devil have in common?

【讨论】:

  • Aaron Bertrand 博客的链接非常有用,因为它解释了为什么在对日期时间列使用 BETWEEN 查询时会提出问题。我很久以前就学会了总是说between '1/1/2016 00:00:00' and 1/31/2016 23:59:59' 而不是between '1/1/2016' and 1/31/2016',但一直没有时间去探究为什么。
  • @JamesToomey 是的,这篇博文非常出色。您意识到如果列的类型允许毫秒,您的 BETWEEN 将失败(我希望您没有真正在日期/日期时间文字中使用 m/d/yyyy 格式!)
  • @TypoCubeᵀᴹ,我可能要暴露我的无知了,但我总是喜欢学习新的东西——m/d/yyyy 进行查询有什么危险?我喜欢yyyy/mm/dd 用于屏幕输出,因为如果此人复制/粘贴到文本文件/其他内容,它将按字母顺序排序,但我怀疑您所说的更多是关于从查询返回不准确数据的风险。 ..
  • 正确,当它用于输出时,没关系,以用户喜欢的任何格式输出。但是对于输入(例如插入、查询/过程中的参数)存在某些问题。我有一些解决模棱两可格式问题​​的答案,但我会向您推荐 Aaron 的另一个帖子:Bad habits to kick : mis-handling date / range queries
  • 感谢您的链接!关于m/d/yyyyd/m/yyyy 的非常好的观点。作为美国人,我习惯了m/d,但它从来没有多大意义(不应该从最小到最大)吗? Scott Hanselman 提到在 9 月 11 日讨论 9/11,他的德国朋友认为他指的是柏林墙倒塌中的 9/11:(link
【解决方案4】:

明确的写法是(即,将第二个日期加 1 并将其设为 &lt;

select * 
from xxx 
where dates >= '20121026'
  and dates <  '20121028'

如果您使用的是 SQL Server 2008 或更高版本,则可以在保留 SARGability 的同时将 CAST 安全地转换为 DATE,例如

select * 
from xxx 
where CAST(dates as DATE) between '20121026' and '20121027'

这明确告诉 SQL Server 您只对 dates 列的 DATE 部分感兴趣,以便与 BETWEEN 范围进行比较。

【讨论】:

    【解决方案5】:

    尝试使用以下查询

    select * 
    from xxx 
    where convert(date,dates) >= '2012-10-26' and convert(date,dates) <= '2012-10-27'
    

    【讨论】:

      【解决方案6】:

      您的问题没有问如何正确使用 BETWEEN,而是就意外截断的结果寻求帮助...

      正如在其他答案中提到/暗示的那样,问题是除了日期之外您还有时间段。

      根据我的经验,使用日期差异值得在键盘上额外磨损/撕裂。它使您可以准确地表达您想要的东西,并且您被覆盖了。

      select * 
      from xxx 
      where datediff(d, '2012-10-26', dates) >=0
      and  datediff(d, dates,'2012-10-27') >=0
      

      使用 datediff,如果第一个日期在第二个日期之前,你会得到一个正数。上面有几种写法,例如总是先有字段,然后是常量。只是翻转运算符。这是个人喜好的问题。

      您可以通过删除一个或两个等号来明确您是要包含端点还是不包含端点。

      BETWEEN 将适用于您的情况,因为端点都被假定为午夜(即 DATE)。 如果您的端点也是 DATETIME,则使用 BETWEEN 可能需要更多的转换。 在我看来,DATEDIFF 被放在我们的生活中,以使我们免受这些问题的影响。

      【讨论】:

        猜你喜欢
        • 2019-03-14
        • 2014-06-11
        • 2021-11-15
        • 2013-04-16
        • 2016-08-04
        • 1970-01-01
        • 2011-08-29
        • 2021-05-19
        • 1970-01-01
        相关资源
        最近更新 更多