我知道您说过该EndDate
列必须允许NULL
,所以仅作记录:最有效的方法是停止使用NULL
s 代替表中的“无结束日期” IdentificationType
,而是使用9999-12-31
. 然后您的查询可以跳过整个OR
子句。(我知道这可能需要对应用程序进行一些更改,但出于这个确切原因,我认为这是值得的——而且我已经看到这种“NULL = 开放式”模式使查询变得困难或一次又一次地表现不佳工作和在线 SQL 问题。)
此外,您可能会考虑交换这两个OR
条件的顺序——这听起来像是巫术,但我相信我听说有一些特殊情况,在这种特定情况下,当变量首先出现时它可以更好地优化(尽管我可能是错的)。
同时,您会尝试这个并分享与您的解决方案和其他解决方案相比它的性能如何?
SELECT
CustomerNumber, IdentificationNumber
FROM
dbo.Identification i
INNER JOIN dbo.IdentificationType it
ON it.IdentificationType = i.IdentificationType
WHERE
it.EffectiveDate < @TodaysDate
AND it.EndDate IS NULL
UNION ALL
SELECT
CustomerNumber, IdentificationNumber
FROM
dbo.Identification i
INNER JOIN dbo.IdentificationType it
ON it.IdentificationType = i.IdentificationType
WHERE
it.EffectiveDate < @TodaysDate
AND it.EndDate > @TodaysDate
;
通过使用这种精确的策略,我已经从OR
子句的糟糕表现中恢复过来。爆炸查询大小/复杂性是很痛苦的,但是与您现在处理的扫描相比,只进行几次搜索的可能性是完全值得的。
您的不等式比较有些可疑:第一个比较应该有一个等号<=
。您没有告诉我们日期列 和 的数据类型@TodaysDate
,但最佳做法是设计一个系统,使其不会因任何输入而失败。因此,即使变量是datetime
并且EffectiveDate
没有时间部分,它仍然应该<=
在该比较中,因此恰好在午夜的查询不会包含当天的数据。
PS 很抱歉没有保留您的格式——我只是在以我喜欢的样式格式化时更好地理解查询。此外,我将日期条件移至WHERE
子句,因为在我看来它们不是JOIN
.