Hoi Ronald,
Voor SQL Server is het antwoord dat het voor een INNER JOIN "in principe" (zie onder) niet uitmaakt. Bij een OUTER JOIN is het anders - hier heeft de locatie van de join invloed op de betekenis.
Bijvoorbeeld:
select L.*, R.* -- Gebruik nooit SELECT * in productie!
from L
left outer join R
on L.id = R.id
and R.kolom = 'ABC'; -- Altijd statements afsluiten met puntkomma!
In dit geval wordt elke kolom van L gekoppeld aan elke rij in R met dezelfde id en die in kolom de waarde ABC heeft - en als dat meer dan één rij is wordt de rij uit L gedupliceerd (tot zover net als bij inner join). Een rij in L die niet gekoppeld kan worden aan een ABC-rij in R blijft gehandhaafd, met NULL waarden in de R kolommen.
select L.*, R.* -- Gebruik nooit SELECT * in productie!
from L
left outer join R
on L.id = R.id
where R.kolom = 'ABC'; -- Altijd statements afsluiten met puntkomma!
Nu wordt elke kolom van L gekoppeld aan elke rij in R met dezelfde id, ongeacht de waarde in kolom - en als dat meer dan één rij is wordt de rij uit L gedupliceerd (tot zover net als bij inner join). Een rij in L die niet gekoppeld kan worden aan een ABC-rij in R blijft gehandhaafd, met NULL waarden in de R kolommen. Hierna worden alle rijen uit het resultaat van de join gefilterd op ABC - dus alle rijen die door de outer join gehandhaafd waren worden alsnog verwijderd uit het resultaat.
(Dit is de logische verwerking - de optimizer is slim genoeg om te zien dat dit een nodeloos ingewikkelde manier is om een inner join te schrijven en hem zo uit te voeren).
select L.*, R.* -- Gebruik nooit SELECT * in productie!
from L
left outer join R
on L.id = R.id
where R.kolom IS NULL; -- Altijd statements afsluiten met puntkomma!
Lijkt op de vorige, maar het filter is nu NULL. Je krijgt dus alleen de rijen uit L die geen enkele match hadden in R, of die een match hadden in R waarvoor kolom in de R tabel al NULL was. Als deze kolom een NOT NULL restrictie heeft is dit een alternatieve schrijfwijze voor NOT EXISTS. (En in hele oude versies van SQL Server soms sneller, dus sommige oudere SQL Server developers gebruiken deze nog steeds - want waarom zou je ook proberen bij te blijven, toch?)
select L.*, R.* -- Gebruik nooit SELECT * in productie!
from L
left outer join R
on L.id = R.id
where ( R.kolom IS NULL or R.kolom = 'ABC'); -- Altijd statements afsluiten met puntkomma!
Dit is een versie die ik wel eens in echte code ben tegengekomen. Eerst worden R en L gekoppeld op id, maar L rijen zonder match in R blijven gehandhaafd. Daarna wordt gefilterd op NULL (dus: geen match) of ABC. Je krijgt dan in het resultaat alle L die geen rij in R hebben met een andere waarde dan ABC. Concreet voorbeeld: welke kinderen op het kamp houden van andijvie of hebben geen voorkeurseten opgegeven?
En deze is dus heel anders dan:
select L.*, R.* -- Gebruik nooit SELECT * in productie!
from L
left outer join R
on L.id = R.id
and ( R.kolom IS NULL or R.kolom = 'ABC'); -- Altijd statements afsluiten met puntkomma!
... want nu krijg je alle kinderen (door de outer join blijft L geheel bestaan), met óf de voorkeur voor andijvie of voor een leeg bord als die voorkeur is opgegeven, of anders zonder informatie over de voorkeur.
"in principe"
De SQL Server optimizer mag de query uitvoeren zoals hij wil. Dus als er (zoals bij inner join) geen verschil is, dan zal je normaal gesproken hetzelfde execution plan krijgen, ongeacht of je dingen in de ON of in de WHERE hebt. Maar als je heel complexe queries krijgt, dan neemt het aantal mogelijkheden voor de optimizer exponentioneel toe, en dan zal de optimizer op een gegeven moment besluiten dat het beter is het "good enough" plan te gebruiken ipv nog twintig minuten te zoeken naar een besparking van 3 seconden. M.a.w., dan worden niet alle mogelijke plannen onderzocht. In zo'n geval kan een wijziging in de query ertoe leiden dat een ander deel van de mogelijke plannen binnnen de tijd bekeken kan worden. Het verband tussen de wijziging in de query en de wijziging in het plan is echter niet te voorspellen, en ik raad dit niet aan als een methode voor performance verbetering - te veel factoren maken dit ook voor de toekomst onvoorspelbaar, en er zijn altijd betere manieren om een probleem in een execution plan te verhelpen.