INNER JOIN
og CROSS APPLY
(samme med LEFT JOIN
og YDRE APPLY
) er meget nært beslægtede. I dit eksempel vil jeg antage, at motoren vil finde den samme udførelsesplan.
- En
JOIN
er et link mellem to sæt over en betingelse - en
APPLY
er en rækkevis underopkald
Men - som nævnt ovenfor - er optimeringsværktøjet meget smart og vil - i hvert fald i så lette tilfælde - forstå, at det kommer ned på det samme.
JOIN
vil prøve at samle undersættet og linke det over den angivne tilstand- Koden
APPLY vil forsøge at kalde det relaterede resultat med den aktuelle rækkes værdier igen og igen.
Der er forskelle i at kalde tabel-værdi-funktioner (skal være inline -syntaks!), med XML-metoden .nodes()
og med mere komplekse scenarier.
Et eksempel på, hvordan man kunne bruge APPLY
at simulere variabler
...for at bruge resultatet af en rækkevis beregning som om du ville bruge en variabel:
ERKLÆR @dummy TABLE(ID INT IDENTITY, SomeString VARCHAR(100));INSERT INTO @dummy VALUES('Vil opdele/dette ved de to/skråstreger.'),('Og/dette/også ');SELECT d.ID ,d.SomeString ,pos1 ,pos2 ,LEFT(d.SomeString,pos1-1) ,SUBSTRING(d.SomeString,pos1+1,pos2-pos1-1) ,SUBSTRING(d.SomeString, pos2+1.1000)FRA @dummy AS dCROSS APPLY(SELECT CHARINDEX('/',d.SomeString) AS pos1) AS xCROSS APPLY(SELECT CHARINDEX('/',d.SomeString,x.pos1+1) AS pos2 ) SOM y
Dette er det samme som det følgende, men meget nemmere at læse (og skrive):
SELECT d.ID ,d.SomeString ,LEFT(d.SomeString,CHARINDEX('/',d.SomeString)-1) ,SUBSTRING(d.SomeString,CHARINDEX('/',d.SomeString) )+1,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))-(CHARINDEX('/',d.SomeString)+1)) ,SUBSTRING(d. SomeString,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))+1.1000)FRA @dummy AS d
Et eksempel med XML-metoden .nodes()
DECLARE @dummy TABEL(SomeXML XML)INSERT INTO @dummy VALUES(N' a1
a2
a3
Her er b! ');SELECT All_a_nodes.value(N'.',N'nvarchar(max)')FROM @dummyCROSS APPLY SomeXML.nodes(N'/root/a' ) AS A(All_a_nodes);
Resultatet
a1a2a3
Og et eksempel på et indlejret funktionskald
CREATE FUNCTION dbo.TestProduceRows(@i INT)RETURNER TABLEASRETURN SELECT TOP(@i) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr FRA master..spt_valuesGOCREATE TABLE dbo.TestData(ID INT IDENTITY, SomeString VARCHAR(100),Number INT);INSERT INTO dbo.TestData VALUES ('Vis mig én gang',1),('Vis mig to gange',2),('Mig fem gange!',5);SELECT *FRA TestDataCROSS ANVEND dbo.TestProduceRows(Number) AS x;GODROP TABLE dbo.TestData;DROP FUNCTION dbo.TestProduceRows;
Resultatet
1 Vis mig en gang 1 12 Vis mig to gange 2 12 Vis mig to gange 2 23 Mig fem gange! 5 13 Mig fem gange! 5 23 Mig fem gange! 5 33 Mig fem gange! 5 43 Mig fem gange! 5 5