INNER JOIN
và CROSS APPLY
(tương tự với LEFT JOIN
và OUTER APPLY
) có liên quan rất chặt chẽ. Trong ví dụ của bạn, tôi giả sử rằng công cụ sẽ tìm thấy cùng một kế hoạch thực thi.
- Một
JOIN
là liên kết giữa hai tập hợp qua một điều kiện - một
APPLY
là một người khôn ngoan cuộc gọi phụ
Nhưng - như đã đề cập ở trên - trình tối ưu hóa rất thông minh và sẽ - ít nhất là trong những trường hợp dễ dàng như vậy - hiểu rằng nó hoạt động giống nhau.
-
JOIN
sẽ cố gắng thu thập tập hợp con và liên kết nó vượt quá điều kiện được chỉ định -
APPLY
sẽ cố gắng gọi kết quả có liên quan với các giá trị của hàng hiện tại lặp đi lặp lại.
Sự khác biệt là trong cách gọi bảng-giá trị-hàm (phải là nội tuyến -syntax!), với XML-method .nodes()
và với các tình huống phức tạp hơn.
Một ví dụ về cách người ta có thể sử dụng APPLY
để mô phỏng biến
... để sử dụng kết quả của một hàng thông minh tính toán giống như bạn sử dụng một biến:
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
Điều này giống như sau, nhưng dễ đọc (và nhập) hơn nhiều:
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
Một ví dụ với XML-method .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);
Kết quả
a1
a2
a3
Và một ví dụ cho lệnh gọi hàm nội tuyến
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;
Kết quả
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