【问题标题】:How to use between clause for getting data between two dates?如何使用 between 子句获取两个日期之间的数据?
【发布时间】:2013-03-28 12:52:39
【问题描述】:

我在数据库中有日期字段,格式为 2012-03-17 19:50:08.023

我想创建一个选择查询,它为我提供 3 月 月份收集的数据。 但我无法做到这一点。

我正在尝试以下查询。

select * from OrderHeader where
Convert(varchar,UploadDt,103) between '01/03/2013' and '31/03/2013' 
and DistUserUniqueID like  '6361%' 

此查询为我提供所有日期的数据。

select * from OrderHeader where
UploadDt between '01/03/2013' and '31/03/2013' and DistUserUniqueID like  '6361%' 

这个查询给我的错误是 Msg 242, Level 16, State 3, Line 1 将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。

请帮我解决这个问题。

提前致谢

【问题讨论】:

  • 使用 varchar (11)。指定长度

标签: sql sql-server


【解决方案1】:

第一个查询返回所有日期,因为您将列转换为字符串。不知道你为什么要这样做。因此,当您说BETWEEN '01/anything' AND '31/anything' 时,当您认为它现在只是一个字符串时,它将匹配列中的所有“日期”,无论月份和年份如何,因为您的WHERE 子句将涵盖可能的每一天(好吧,除了 3 月以外的第 31 个月,以及 1 月和 2 月的第一天——所以不是所有的数据,而是一个很大的百分比)。例如,'15/11/2026'BETWEEN '01\03\2013' AND '31/03/2013'

想一想。您的数据库中有日期时间数据,并且您希望在查询之前将其转换为字符串。在比较之前,您还会将薪水转换为字符串吗?如果是这样,赚 70,000 美元的人看起来比赚 690,000 美元的人赚的更多,因为基于字符的排序从第一个字符开始,不考虑长度。

第二个查询失败,因为您对日期使用了区域性、不明确的格式。你可能喜欢dd/mm/yyyy,但显然你的服务器是基于美国英语格式的,而mm/dd/yyyy应该是这样的。

解决方案是使用适当的、明确的格式,例如YYYYMMDD

BETWEEN '20130301' AND '20130313'

但是you shouldn't use BETWEEN - 因为这是您应该使用的DATETIME 列:

WHERE UploadDt >= '20130301'
  AND UploadDt <  '20130401'

(否则您将错过从2013-03-31 00:00:00.0012013-03-31 23:59:59.997 的所有数据。)

如果你真的很喜欢BETWEEN,那么在 2008+(你没有告诉我们你的版本)你可以使用:

WHERE CONVERT(DATE, UploadDt) BETWEEN '20130301' AND '20130331'

更多与日期相关的提示:

最后,when converting to VARCHAR (or any variable-length data types), always specify a length

【讨论】:

    【解决方案2】:

    将查询重写为

    select * from OrderHeader where
    UploadDt between '01/03/2013' and '01/04/2013' 
    and DistUserUniqueID like  '6361%'
    

    select * from OrderHeader where
    UploadDt between Convert(datetime,'01/03/2013', 103) and Convert(datetime,'01/04/2013',103) 
    and DistUserUniqueID like  '6361%'
    

    【讨论】:

    • 这两个都将返回从 4 月 1 日午夜开始的数据。这改变了查询的含义。此外,您的第一个版本仅回避了该问题,因为日期和月份均不超过 12。我怀疑这将返回 1 月 3 日至 1 月 4 日的数据,而不是原始查询的意图。
    • @AaronBertrand:值为 103 的 datetimeformat 参数负责回避。这在我的最后工作正常,我一直在使用它。 103 用于“dd/mm/yyyy”。最好亲自动手,而不是因怀疑而投反对票。 :)
    • 谢谢,我相信我了解 103 如何处理回避问题。但是您的第一个查询中没有 103,对吗?看到我怎么说“你的第一个版本”了吗?这里还有多个其他问题无法解决 OP 的实际问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 2020-03-02
    • 2021-04-11
    • 2020-05-03
    • 2019-05-07
    • 2020-09-26
    • 2021-10-11
    相关资源
    最近更新 更多