SQL Server - 查询短路?

时间:2008-12-19 15:09:44

标签: sql sql-server

SQL Server中的T-SQL查询是否支持短路?

例如,我有一种情况,我有两个数据库,我正在比较两个表之间的数据,以匹配和复制一些信息。在一个表中,“ID”字段将始终具有前导零(例如“000000001234”),而在另一个表中,ID字段可以具有或不具有前导零(可以是“000000001234”或“1234”)。

所以我的查询匹配两者是这样的: select * from table1 where table1.ID LIKE'%1234'

为了加快速度,我想在之前添加一个OR,它只是说: table1.ID = table2.ID 处理两个ID都有填充零并且相等的情况。

这样做是否会通过匹配“=”上的项目而不是为每一行评估LIKE来加速查询(它会短路并跳过LIKE)吗?

7 个答案:

答案 0 :(得分:7)

您可以向表中添加计算列。然后,索引计算列并在连接中使用该列。

例如:

Alter Table Table1 Add PaddedId As Right('000000000000' + Id, 12)
Create Index idx_WhateverIndexNameYouWant On Table1(PaddedId)

然后你的查询将是......

select * from table1 where table1.PaddedID ='000000001234'

这将使用您刚创建的索引快速返回该行。

答案 1 :(得分:7)

SQL Server在条件允许的情况下执行 NOT 短路。 它不能,因为它是一个基于成本的系统:How SQL Server short-circuits WHERE condition evaluation

答案 2 :(得分:3)

您希望确保至少有一个表使用其ID的实际数据类型,并且如果可能,它可以使用索引查找。它取决于查询的选择性和匹配率,但要确定哪一个应该转换为另一个。如果您知道必须扫描整个第一个表,那么无论如何都不能使用搜索,您应该将该ID转换为另一个表的数据类型。

要确保您可以使用索引,还要避免使用LIKE。举个例子,最好有:

WHERE
     T1.ID = CAST(T2.ID AS VARCHAR) OR
     T1.ID = RIGHT('0000000000' + CAST(T2.ID AS VARCHAR), 10)

比:

WHERE
     T1.ID LIKE '%' + CAST(T2.ID AS VARCHAR)

正如Steven A. Lowe所说,第二个查询也可能不准确。

如果你打算使用T1中的所有行(换句话说,LEFT OUTER JOIN到T2)那么你可能会更好:

WHERE
     CAST(T1.ID AS INT) = T2.ID

如果您不确定并查看哪种方法最有效,请对每种方法执行一些查询计划。

绝对最好的路线是正如其他人所建议的那样,并且如果可能的话,更改表格的数据类型以匹配。即使您在此项目到期之前无法执行此操作,也请在不久的将来将其放在“待办事项”列表中。

答案 3 :(得分:3)

怎么样,

table1WithZero.ID = REPLICATE('0', 12-len(table2.ID))+table2.ID

在这种情况下,它应该能够使用table1上的索引

答案 4 :(得分:3)

以防它有用,正如Mladen Prajdic的anwer中的链接页解释的那样,CASE条款 进行了短路评估。

答案 5 :(得分:1)

修复数据库以保持一致

select * from table1 where table1.ID LIKE '%1234'

将匹配'1234','01234','00000000001234',但也匹配'999991234'。使用LIKE几乎可以保证索引扫描(假设table1.ID被索引!)。清理数据将显着提高性能。

如果无法清理数据,请编写用户定义的函数(UDF)以去除前导零,例如

select * from table1 where dbo.udfStripLeadingZeros(table1.ID) = '1234'

这可能无法提高性能(因为函数必须为每一行运行)但它会消除错误匹配并使查询的意图更加明显

编辑:Tom H建议CAST为整数是最好的,如果可能的话。

答案 6 :(得分:1)

如果ID是纯数字的(作为您的示例),我会建议(如果可能)将该字段更改为数字类型。如果数据库已经全部使用,则可能很难更改类型。