【问题标题】:Converting Date in Where clause in SQL在 SQL 的 Where 子句中转换日期
【发布时间】:2020-06-11 15:44:06
【问题描述】:

我需要返回过去 30 天内的总和。我的日期字段是一个文本字段。我的桌子看起来像这样:

Client    Serial#        Hrs        MyDate
A         1              12         20200501
A         1              8          20200513
B         5              2          20200521
B         6              3          20200522
A         2              5          20200528
A         2              2          20200529

我的代码如下所示:

SELECT Client, Serial#, SUM(Hrs)
FROM MyTable
WHERE CONVERT(DATETIME, MyDate, 112) > DATEADD(day, -30, getdate())
GROUP BY Client, Serial#

这是我得到的错误 “将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。”

我尝试删除转换功能并得到另一个错误: “将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。”

所以现在我被困住了。提前感谢您的帮助

【问题讨论】:

  • "我的日期字段是一个文本字段。" -- 这就是麻烦开始的地方...使用适当的日期/时间类型,而不是字符串类型。
  • 我希望我的公司也以这种方式存储他们的信息

标签: sql sql-server


【解决方案1】:

您可以使用try_convert() 解决此问题:

WHERE TRY_CONVERT(DATE, MyDate) > DATEADD(day, -30, getdate())

您的格式是 SQL Server 为日期常量定义的格式,因此您实际上不需要格式参数。

您可以使用以下方法找到违规值:

select mydate
from t
where try_convert(date, mydate) is null and mydate is not null;

请注意,dates 和 datetimes 具有不同的范围,因此仅使用 date 可能会解决问题。

【讨论】:

  • 抱歉,这不起作用。说 Try-Convert 不是公认的内置功能。我应该指定我使用的是 Microsoft SQL Server Management Studio 18
  • 该函数有一个下划线,而不是一个破折号。但 SSMS 的版本不相关。您的 sql server 实例的版本是什么,它使用的是什么兼容级别?
  • @Conner 。 . .每个受支持的 SQL Server 版本都支持try_convert()
【解决方案2】:

因为您别无选择,只能使用 varchar 作为日期,所以我会将一个 GETDATE() 值转换为 varchar,而不是将所有行都转换为日期。这是可能的,因为它们存储为 YYYYMMDD。我认为这对性能会更好(当然,如果您在此日期列上有索引)。

WHERE MyDate > CONVERT(varchar(10),dateadd(d,-30,getdate()),112)

【讨论】:

  • 做到了。谢谢!我从没想过让今天的函数匹配字符格式。
【解决方案3】:
SELECT Client, Serial, SUM(Hrs)
FROM MyTable
WHERE CONVERT(DATETIME, MyDate) > DATEADD(day, -30, getdate())
GROUP BY Client, Serial

您不需要格式 112 进行比较

【讨论】:

  • 这是我尝试“将 varchar 数据类型转换为 datetime 数据类型导致超出范围的值”时出现的错误。
  • 查看 Jon Wilson 的回答。这应该是解决方案。
【解决方案4】:

您的转换函数看起来没问题(虽然 112 不需要转到日期时间,即用于日期时间到字符串的转换。) 所以我打赌你在这些日期字符串的某个地方有一些错误的数据。 日期必须介于 1753 年 1 月 1 日至 9999 年 12 月 31 日之间。 尝试对该字段进行排序,看看列表顶部或底部是否有任何可疑的内容。

您可以添加一个过滤器:

    AND MyDate BETWEEN '17530101' and '99991231'
    AND LEN(MyDate) = 8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 2020-08-24
    相关资源
    最近更新 更多