【问题标题】:error executing a query with date check in where clause在 where 子句中使用日期检查执行查询时出错
【发布时间】:2020-03-12 15:13:27
【问题描述】:

我有一个表,其中年份和月份值分别保存为 int 数据类型列 [Year] 和 [Month]。我需要使用 WHERE 子句查询将输出限制在某个日期的表。我想出了一个使用 DATEFROMPARTS 函数的解决方案(避免数据类型的多次转换),它在 SELECT 子句中完美运行(不同日期的数量是有限的,所以我可以检查所有这些),但是当我尝试使用时失败了WHERE 子句中的复合日期。

这样查询

SELECT DISTINCT DATEFROMPARTS([Year], [Month], 1) FROM MyTable 

给予

2019-04-01
2019-05-01
2019-06-01
2019-07-01
2019-08-01
2019-09-01
2019-10-01
2019-11-01
2019-12-01
2020-01-01
2020-02-01
2020-03-01

但是当我添加一个像这样的 WHERE 子句时

SELECT DISTINCT DATEFROMPARTS([Year], [Month], 1) FROM MyTable 
WHERE DATEFROMPARTS([Year], [Month], 1) < convert(date, getdate(), 23)

SELECT DISTINCT DATEFROMPARTS([Year], [Month], 1) FROM MyTable 
WHERE DATEFROMPARTS([Year], [MonthNumber], 1) < convert (date, '2019-12-01', 23)

我得到一个错误:

无法构造数据类型日期,某些参数的值无效。

我正在使用 SQL Server 版本。 13

免责声明 数据存储在我从云机器访问的远程 SQL 服务器上。这是一个视图,我对它的权限为零,只能在 ETL 过程中进一步阅读和使用它。 Year 和 Month 列中 no 存在非法值,例如 NULL、Month > 12 等。

更新 我在 SQL Server 2016 上尝试过类似的场景:

CREATE TABLE MyTable(
    [Year] [int] NULL,
    [Month] [int] NULL)

INSERT INTO MyTable
           ([Year], [Month])
     VALUES
          (2019, 9)
         ,(2019, 10)
         ,(2019, 11)
         ,(2019, 12)
         ,(2020, 1)
         ,(2020, 2)
         ,(2020, 3)
         ,(2020, 4)

DATEFROMPARTS 或连接 dateparts 并转换为不同格式的日期的组合不起作用,充其量,日期仅在 yyyy-mm-dd 格式下看起来不错,但无法与 getdate() 函数进行比较。

@John-Cappelletti 提出的解决方案帮助解决了最初的问题:

try_convert(date, concat([Year],'/',[Month],'/', 1))

虽然我仍然不清楚为什么不能将组合日期转换为不同的日期样式。

【问题讨论】:

  • 假设 SQL Server 版本 13 是指 SQL Server 2016?
  • 您能否提供一些可以复制问题的示例数据?
  • 根据假定示例数据,我无法复制您的问题。 DB<>Fiddle
  • 你想要哪种形式的数据?
  • DDL 和 DML 最好,如果不是表格格式text

标签: sql sql-server tsql date


【解决方案1】:

由于数据问题,可能使用try_convert()concat()

示例

Declare @YourTable Table ([Year] int,[Month] int)  
Insert Into @YourTable Values 
 (2020,1)
,(2020,1)
,(2020,2)
,(2020,222)

Select * 
      ,try_convert(date,concat([Year],'/',[Month],'/', 1))
 From @YourTable

退货

Year    Month   (No column name)
2020    1       2020-01-01
2020    1       2020-01-01
2020    2       2020-02-01
2020    222     NULL          << There's a problem

【讨论】:

  • 谢谢,您的转换方法最终奏效了。尽管在您的示例中,我没有任何非法的年份或月份值。而且我仍然不明白为什么它不能与“-”等其他日期分隔符一起使用,甚至“/”也不能转换为某种格式的日期(例如 112 或 104)。
  • @user12197757 总是乐于提供帮助。可以是 NULLS 还是字符串(带有尾随空格)?重要的是将其转换为日期,然后您可以根据需要应用所需的格式:)
  • 两列都定义为 int。使用 DISTINCT 检查没有发现任何 NULLS 或月份 > 12
  • @user12197757 假年份?这是唯一剩下的:)
【解决方案2】:

离开23

WHERE DATEFROMPARTS([Year], [Month], 1) < convert(date, getdate())

您可能对国际化设置有疑问。您的版本正在将 getdate() 转换为字符串并返回日期。

【讨论】:

  • 23 样式代码应该没有任何影响。当您不从(n)varchar 转换或转换为(n)varchar 时,样式代码将被有效地忽略。由于 OP 正在从 datetime 转换为 date 它不会做任何事情。对于CONVERT(date,GETDATE(),23)CONVERT(date,GETDATE()),我得到了2020-03-12 的结果。 OP 的错误也特定于 DATEFROMPARTS,而不是 CONVERT
  • getdate() 以相同的格式返回日期:2020-03-12 18:23:49.640 另外,我尝试在
【解决方案3】:

DATEFROMPARTS(YEAR,MONTH,DAY) 将返回 DATE 格式的值。

只需CAST 您要以相同格式与之比较的参数即可。那你是在比较相同类型的格式吗?

您之前遇到的错误是因为您正在尝试转换为不同的数据类型。

SELECT DISTINCT DATEFROMPARTS([Year], [Month], 1) 
FROM MyTable 
WHERE DATEFROMPARTS([Year], [Month], 1) < CAST(GETDATE() as DATE)

【讨论】:

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