简体   繁体   中英

Left Join with OR operator precedence

I have the following query:

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])

What I am trying to figure out are a couple of things.

First what I had before was this pseudo code:

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

I am trying to convert this psuedo code to the SQL up above. At first I had a scalar function that had the IF's in it but that turned out to be very slow.

Right now, the above left join is working, and is much faster, but I am wondering what the precedence of the statements are in the Left Join?

Also, If 1 OR statement is true, and another OR statement is true, and they are true on different records in the #Test table, what happens?

Is there any better alternatives to this as well?

EDIT: The Tables are as follows:

Driver
LicenseNumber, Birthdate,LastName,FirstName

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

Basically what I am trying to do is pull the Address from the #Test table.

As a rule, OR does not short-circuit. It CAN but it is not guaranteed to.

Basically the query optimizer looks at the conditions, and determines the fastest way to execute taking into account the statistics available. If it looks like condition 2 will be quicker to test than condition 1 (say for instance the first condition will require a table scan but the second one can use an index seek then the optimizer is likely to check the second condition FIRST.

It may also run them concurrently if that looks quicker, then do a join behind the scenes and eliminate duplicates.

First, I want to point out that if you need to do this, your design is flawed and what you should be doing is fixing your design first. For instance if there are two records meeting different criteria with different addresses, how do you know which is the right one? You don't have a field that tells you the date of the record which would make it easy and avoid all this nonsense. Next, any time you have to do a lot of functions in a join, your data model is flawed. Liscence number should be stored exactly the same way every time in any field in which it is stored. SInce you are getting it from a temp table, why don;t you fix the data when you put it into the temp table if you can't fix the data model.

The way OR works is that it will retreive any record that meets any one of the conditions. It doesn't care what order they are in or if there is already a differnt record for that person. If you want only one record for a person based on a precendence what you want is a UNION (and not UNION ALL) Statement. Write the SQl to get the data for the first condition, then union it to the data for second condition etc. This will not be particularly fast but is how you would know that the record you selected was in correct precedence order.

That SQL query will do as many joins as it can on the tables. A left join is "greedy" in a way there is no precedence in join statement conditionals like that.

Basically, if a driver meets more than one of those conditionals then you will end up with multiple rows for the same driver. You could try adding SELECT DISTINCT to that sql statement to limit duplicates driver rows, but I'm not sure that it will follow any kind of precedence of your conditional when eliminating duplicates. You'll have to look at the query strategy to know when the filtering is done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM