SQL中的LEFT在没有与JOIN配对时会做什么,为什么它会导致我的查询超时?

时间:2012-06-14 17:40:48

标签: sql timeout

我收到了以下声明:

LEFT(f.field4, CASE WHEN PATINDEX('%[^0-9]%',f.field4) = 0 THEN LEN(f.field4) ELSE PATINDEX('%[^0-9]%',f.field4) - 1 END)=@DealNumber

并且无法联系撰写该文章的人。有人可以解释一下该语句的作用,以及它是否是有效的SQL?该语句的目标是将f.field中的数字字符与DealNumber进行比较。除了DealNumber末尾的通配符外,DNumber和DealNumber是相同的。

我试图在以下语句的上下文中使用它:

SELECT d.Description, d.FileID, d.DateFiled, u.Contact AS UserFiledName, d.Pages,   d.Notes
FROM Documents AS d
LEFT JOIN Files AS f ON d.FileID=f.FileID
LEFT JOIN Users AS u ON d.UserFiled=u.UserID
WHERE SUBSTRING(f.Field8, 2, 1) = @LocationIDString
AND f.field4=@DNumber OR LEFT(f.field4, CASE WHEN PATINDEX('%[^0-9]%',f.field4) = 0 THEN LEN(f.field4) ELSE PATINDEX('%[^0-9]%',f.field4) - 1 END)=@DealNumber"

但是当我执行它时,我的代码会保持超时。

2 个答案:

答案 0 :(得分:2)

这是CASE子句,它减慢了速度,而不是LEFT本身(尽管LEFT可能会阻止使用索引,这会产生影响)。

CASE确定应与@DealNumber进行比较的内容,我认为它会执行以下操作...

如果f.field4没有以数字开头,请使用LEFT(f.field4, LEN(f.field4))=@DealNumber:相当于f.field4=@DealNumber
如果f.field4确实以数字开头,请使用{those digits}=@DealNumber

这种计算效率不高。

我会尝试以下操作,这会使假设混合字符串可以转换为整数 - 也就是说,如果将ABC转换为整数,则会得到零,如果您转换123ABC,您将获得可转换的内容123。我找不到任何文件说明这是否可能。

AND f.field4=@DNumber
OR (f.field4=@DealNumber AND integer(f.field4)=0)
OR (integer(f.field4)=@DealNumber)

第一行与AND相同。仅当f.field4=@DealNumber不以数字开头时,第二行才会选择f.field4。第三行选择f.field4的初始数字部分与@DealNumber相同的位置。

正如我所说,这里假设integer()将以这种方式运作。您可能需要定义CAST函数以使用字符串进行转换。这远远超出了我,尽管我相信即使这样的功能也会比你现在拥有的CASE更快。

答案 1 :(得分:1)

来自doc

  

left(str text,n int)

     

返回字符串中的前n个字符。当n为负数时,返回除最后| n |之外的所有内容字符。