在SQL的Where子句中转换日期

时间:2020-06-11 15:44:06

标签: sql sql-server

我需要返回过去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数据类型转换为日期时间数据类型会导致超出范围的值。”

我尝试删除转换函数,并遇到另一个错误: “将varchar数据类型转换为日期时间数据类型会导致超出范围的值。”

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

4 个答案:

答案 0 :(得分:1)

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

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

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

您可以使用以下方法找到有问题的值:

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

请注意,datedatetime的范围不同,因此仅使用date可能会解决此问题。

答案 1 :(得分:0)

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

您不需要112格式进行比较

答案 2 :(得分:0)

您的转换功能看起来还不错(尽管112不需要去日期时间,也就是用于日期时间到字符串的转换。) 因此,我敢打赌,这些日期字符串中的某些地方会有一些不良数据。 日期必须在1753年1月1日至9999年12月31日之间。 尝试对该字段进行排序,看看列表的顶部或底部是否有可疑的东西。

您可以添加一个过滤器:

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

答案 3 :(得分:0)

因为您别无选择,只能使用varchar作为日期,所以我会将一个GETDATE()值转换为varchar,而不是将所有行都转换为日期。可能是因为它们存储为YYYYMMDD。我认为这会提高性能(确定在此日期列上是否有索引)。

WHERE MyDate > CONVERT(varchar(10),dateadd(d,-30,getdate()),112)
相关问题