【问题标题】:Meaning of CAST('1/1' + ...... as DATETIME)?CAST('1/1' + ...... as DATETIME) 的含义?
【发布时间】:2026-02-03 02:00:02
【问题描述】:

在以下 T-SQL 代码中:

wt.clsdt_date >= CAST('1/1/' + CAST(2011 - 1 AS varchar) AS DateTime)

“1/1”是什么意思?

【问题讨论】:

  • 虽然我很欣赏有关编写上述代码的最佳方式的所有建议,但恐怕我对它的编写方式无能为力,无论它多么复杂。我无权访问代码来进行适当的更改。我只是想将它从 Word 文档转换为 LINQ to SQL。但是,您的解释对于准确解释正在发生的事情非常有帮助,为此我感谢大家。

标签: sql-server tsql


【解决方案1】:

(请参阅其他答案以了解对 SQL 的改进。)

'1/1/' 是字符串,所以+ 之后的结果字符串是'1/1/year',例如

   '1/1/' + CAST(2011 - 1 as varchar)
-> '1/1/' + '2010'
-> '1/1/2010'

然后将其强制转换(实际上是转换)为适当的类型。

如果没有更漂亮的方法来做到这一点,我会感到惊讶。

对于 SQL Server 2008 及之前的there does not appear to be a particularly nice standard method

对于 SQL Server 2012,有 DATEFROMPARTS,如 this related SO post 所示:

SELECT DATEFROMPARTS(@Year, @Month, @Day)

【讨论】:

  • 好的。感谢您的帮助。
  • 请注意,DATEFROMPARTS 是 SQL Server 2012 中的新功能。
【解决方案2】:

更安全的方法是:

WHERE wt.clsdt_date >= CONVERT(CHAR(4), 2011 - 1) + '0101';

您无需将其显式转换为 datetime,但您可以:

WHERE wt.clsdt_date >= CONVERT(DATETIME, CONVERT(CHAR(4), 2011 - 1) + '0101');

这使用非区域日期格式,并且仍然使用列上的索引(如果存在)。

还有varchar without length is a bad habit.

【讨论】:

  • +1 虽然在这种特殊情况中'1/1/yyyy'应该是“安全的”?请注意,我并不是反对这种方法。
  • @pst 重点是人们可能会从1/1/ 示例中学习并假设它对6/15/ 也是安全的(这可能会产生错误),或者更糟糕的是6/7/ 这可能会导致错误结果,但未被发现。
  • 是的,我完全同意,这是一个更好的习惯/方式来编写它。我只是想知道它是否会影响这个特定的字符串输入。
【解决方案3】:

此技术用于评估 wt.clsdt_date 是否在 2010 年期间或之后。完成此操作的更简洁方法如下:

YEAR(wt.clsdt_date) >= 2010

【讨论】:

  • 这不是 sargable。用YEAR 函数包裹列意味着不能使用索引。
  • @MartinSmith Lame,我希望规划者能够在那里做一些扣除......
  • @pst - 大多数情况下它不会,即使原则上它可以。 There is a request to extend the cases where it does here
  • @MartinSmith - 它似乎已关闭
  • @Lamak 这并不意味着如果您投票并添加 cmets 以后不会考虑它。 :-) 不幸的是,在这种情况下,“关闭”实际上意味着“至少在当前版本中关闭”。