INNER JOIN
dan CROSS APPLY
(sama dengan LEFT JOIN
dan OUTER APPLY
) sangat erat hubungannya. Dalam contoh Anda, saya berasumsi bahwa mesin akan menemukan rencana eksekusi yang sama.
- Sebuah
JOIN
adalah penghubung antara dua himpunan pada suatu kondisi - sebuah
APPLY
adalah bijaksana baris sub-panggilan
Tetapi - seperti yang disebutkan di atas - pengoptimal sangat cerdas dan akan - setidaknya dalam kasus yang begitu mudah - memahami, bahwa hal itu sama saja.
JOIN
akan mencoba mengumpulkan subkumpulan dan menautkannya atas kondisi yang ditentukanAPPLY
akan mencoba memanggil hasil terkait dengan nilai baris saat ini berulang-ulang.
Perbedaannya terletak pada pemanggilan table-valued-functions (harus sebaris -sintaks!), dengan metode XML .nodes()
dan dengan skenario yang lebih kompleks.
Salah satu contoh bagaimana seseorang dapat menggunakan APPLY
untuk mensimulasikan variabel
...untuk menggunakan hasil bijaksana baris perhitungan seperti Anda akan menggunakan variabel:
DECLARE @dummy TABLE(ID INT IDENTITY, SomeString VARCHAR(100));
INSERT INTO @dummy VALUES('Want to split/this at the two/slashes.'),('And/this/also');
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)
FROM @dummy AS d
CROSS APPLY(SELECT CHARINDEX('/',d.SomeString) AS pos1) AS x
CROSS APPLY(SELECT CHARINDEX('/',d.SomeString,x.pos1+1) AS pos2) AS y
Ini sama dengan yang berikut ini, tetapi lebih mudah dibaca (dan diketik):
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)
FROM @dummy AS d
Salah satu contoh dengan metode XML .nodes()
DECLARE @dummy TABLE(SomeXML XML)
INSERT INTO @dummy VALUES
(N'<root>
<a>a1</a>
<a>a2</a>
<a>a3</a>
<b>Here is b!</b>
</root>');
SELECT All_a_nodes.value(N'.',N'nvarchar(max)')
FROM @dummy
CROSS APPLY SomeXML.nodes(N'/root/a') AS A(All_a_nodes);
Hasilnya
a1
a2
a3
Dan satu contoh untuk pemanggilan fungsi sebaris
CREATE FUNCTION dbo.TestProduceRows(@i INT)
RETURNS TABLE
AS
RETURN
SELECT TOP(@i) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr FROM master..spt_values
GO
CREATE TABLE dbo.TestData(ID INT IDENTITY, SomeString VARCHAR(100),Number INT);
INSERT INTO dbo.TestData VALUES
('Show me once',1)
,('Show me twice',2)
,('Me five times!',5);
SELECT *
FROM TestData
CROSS APPLY dbo.TestProduceRows(Number) AS x;
GO
DROP TABLE dbo.TestData;
DROP FUNCTION dbo.TestProduceRows;
Hasilnya
1 Show me once 1 1
2 Show me twice 2 1
2 Show me twice 2 2
3 Me five times! 5 1
3 Me five times! 5 2
3 Me five times! 5 3
3 Me five times! 5 4
3 Me five times! 5 5