左连接OR运算符优先级

时间:2011-07-19 20:08:17

标签: sql sql-server

我有以下查询:

SELECT * FROM 
dbo.Driver d
    LEFT JOIN #Test t ON  
       ((d.LicenseNumber = REPLACE(REPLACE(t.[LicNumber],'-',''),' ','')) 
        OR 
       (d.[BirthDate] = t.[BirthDate]
        AND  d.[LastName] = t.[LastName]
        AND d.[FirstName] = t.[FirstName])
        OR
       (SUBSTRING(d.[LicenseNumber], PATINDEX('%[^0]%', d.[LicenseNumber] + '.'), LEN(d.[LicenseNumber]))) = t.[LicNoZero])

我想弄清楚的是一些事情。

我之前拥有的是这个伪代码:

IF Driver.License = #Test.DriverLicenseNumber(No Space/Dash) THEN JOIN
ELSE
IF Driver.BirthDate = #Test.BirthDate
AND Driver.LastName = #test.LastName
AND Driver.FirstName = #Test.FirstName THEN JOIN
ELSE
IF Driver.LicenseNoZero = #Test.LicNoZero THEN JOIN
ELSE
DO NOTHING

我正在尝试将此伪代码转换为上面的SQL。起初我有一个标量函数,其中包含IF,但结果却很慢。

现在,上面的左连接工作正常,速度要快得多,但我想知道语句在左连接中的优先级是什么?

此外,如果1个OR语句为真,另一个OR语句为真,并且它们在#Test表中的不同记录中为真,那么会发生什么?

还有更好的替代方案吗?

编辑: 表格如下:

Driver
LicenseNumber, Birthdate,LastName,FirstName

#Test
Licnumber,Birthdate,LastName,FirstName,LicNoZero,Address

基本上我要做的是从#Test表中提取地址。

3 个答案:

答案 0 :(得分:3)

通常,OR不会短路。它 CAN 但不保证。

基本上,查询优化器会查看条件,并根据可用的统计信息确定最快的执行方式。如果看起来条件2将比条件1更快地进行测试(例如,第一个条件将需要table scan,但第二个条件可以使用index seek,那么优化器可能会检查第二个条件条件FIRST。

如果看起来更快,它也可以同时运行它们,然后在幕后进行连接并消除重复。

答案 1 :(得分:2)

首先,我想指出,如果你需要这样做,你的设计是有缺陷的,你应该做的是先修复你的设计。例如,如果有两个记录满足不同地址的不同标准,您如何知道哪个是正确的?你没有一个字段告诉你记录的日期,这将使它变得容易,并避免所有这些废话。接下来,任何时候你必须在连接中执行很多功能,你的数据模型都是有缺陷的。每次在存储它的任何字段中,Liscence数应该以完全相同的方式存储。您是从临时表中获取它的,为什么不这样做;如果无法修复数据模型,则在将数据放入临时表时修复数据。

OR的工作方式是它将检索满足任何一个条件的任何记录。它不关心他们的订单是什么,或者是否已经有该人的不同记录。如果您只想根据优先级为一个人创建一条记录,那么您需要的是UNION(而不是UNION ALL)语句。编写SQl以获取第一个条件的数据,然后将其与第二个条件的数据相结合等。这将不会特别快,但是您将如何知道您选择的记录具有正确的优先顺序。

答案 2 :(得分:0)

SQL查询将在表上执行尽可能多的连接。左连接是“贪婪的”,这种方式在连接语句条件中没有优先权。

基本上,如果驱动程序遇到多个条件,那么最终会为同一个驱动程序提供多行。您可以尝试将 SELECT DISTINCT 添加到该sql语句以限制重复的驱动程序行,但我不确定它在消除重复项时是否会遵循条件的任何优先级。您必须查看查询策略以了解过滤何时完成。