我有一个查询,该查询将int文件转换为最新的文件,并且工作正常。但是,当我将此演员表添加到哪里时,我的查询将不起作用
select
convert(date,CONVERT(varchar(10),t.TimeEntityElementId,101))
from dbo.Time t
where
convert(date,CONVERT(varchar(10),t.TimeEntityElementId,101)) < N'2019-01-01'
答案 0 :(得分:0)
为什么不只使用cast()
? :
select cast(t.TimeEntityElementId as date)
from dbo.Time t
where cast(t.TimeEntityElementId as date) < '2019-01-01';
N
不适合这样做,因为TimeEntityElementId
具有datetime
类型,并且N
代表“本国语言字符集”,这意味着您正在传递{{1 }},NCHAR
或NVARCHAR
类型的数据。
答案 1 :(得分:0)
因此,似乎我们有一个int
值,您确实需要一个DateTime
。在表定义中更正此错误确实可以为您省去很多的麻烦。但是在这种情况下,我们仍然可以利用现有数据进行一些改进。
从此WHERE条件开始:
convert(date,CONVERT(varchar(10),t.TimeEntityElementId,101)) < N'2019-01-01'
此处使用CONVERT()
函数可防止使用TimeEntityElementId
可能具有的任何索引。相反,我们可以利用按顺序大小和位置组织的细分来利用值。这类似于Sql Server实际存储日期/日期时间的方式,但是它每年从整数空间中刻出10,000个数字块,而不是像Sql Server那样刻出365。这意味着您可以大大减少代码并编写与简单的数字比较相同的条件,如下所示:
t.TimeEntityElementId < 20190101
这不需要进行任何逐行转换,并且仍然可以使用TimeEntityElementId
索引,因此应该更快地执行 MUCH ,可能是多个数量级。
当然,您仍然需要担心SELECT端,但是现在您只转换通过WHERE子句的行,而不转换表中的每一行,这足以解决问题。但是我们可以做更多。我们还可以使用DATEFROMPARTS()
函数来删除SELECT转换:
DATEFROMPARTS(t.TimeEntityElementId/10000, (t.TimeEntityElementId % 10000) / 100, t.TimeEntityElementId % 100)
这样可以避免将字符串解析为日期时间,这实际上是一个很慢的操作。上面的表达式令人发疯,这全是数学,CPU可以非常高效地完成。解析字符串必须考虑各种文化/国际化的怪癖,因此往往要慢得多。对于TimeEntityElementId
具有不符合日期格式的行的情况,它也不太敏感。您仍然可以在那里获得奇怪的结果,但至少它不应该只是使整个查询失败。
像这样将它们放在一起:
SELECT
DATEFROMPARTS(t.TimeEntityElementId/10000, (t.TimeEntityElementId % 10000) / 100, t.TimeEntityElementId % 100)
FROM dbo.Time t
WHERE t.TimeEntityElementId < 20190101
但是这些主要是性能方面的改进。他们可能也可以解决您的问题,但这只是一个副作用,我不确定,因为我们对问题出在哪里没有清晰的描述。
这将我带到了最后一点。我们需要更好地了解“无效”的含义。如果没有对错误或错误行为的进一步说明,“不起作用”将永远都不够好。