LEFT JOIN nên được thay thế bằng OUTER APPLY trong các tình huống sau.
1. Nếu chúng ta muốn nối hai bảng dựa trên TOP n kết quả
Cân nhắc xem chúng ta có cần chọn Id không và Name từ Master và hai ngày cuối cùng cho mỗi Id từ Details bảng.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
LEFT JOIN
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID
tạo thành kết quả sau
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | NULL | NULL |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
Điều này sẽ mang lại kết quả sai, tức là nó sẽ chỉ mang lại dữ liệu hai ngày mới nhất từ Details bảng không phân biệt Id mặc dù chúng tôi tham gia với Id . Vì vậy, giải pháp thích hợp là sử dụng OUTER APPLY .
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
OUTER APPLY
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
WHERE M.ID=D.ID
ORDER BY CAST(PERIOD AS DATE)DESC
)D
Đây là cách hoạt động:Trong LEFT JOIN , TOP 2 ngày sẽ được kết hợp với MASTER chỉ sau khi thực hiện truy vấn bên trong bảng dẫn xuất D . Trong OUTER APPLY , nó sử dụng tham gia WHERE M.ID=D.ID bên trong OUTER APPLY , để mỗi ID trong Master sẽ được tham gia với TOP 2 ngày sẽ mang lại kết quả sau.
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | 2014-01-08 | 40 |
| 2 | B | 2014-01-06 | 30 |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
2. Khi chúng ta cần LEFT JOIN chức năng sử dụng các hàm functions .
OUTER APPLY có thể được sử dụng để thay thế bằng LEFT JOIN khi chúng ta cần lấy kết quả từ Master bảng và một hàm functions .
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Và chức năng ở đây.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE example@sqldat.com
)
đã tạo ra kết quả sau
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-11 | 15 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | 2014-01-06 | 30 |
| 2 | B | 2014-01-08 | 40 |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
3. Giữ lại NULL giá trị khi hủy chia sẻ
Hãy xem xét bạn có bảng dưới đây
x------x-------------x--------------x
| Id | FROMDATE | TODATE |
x------x-------------x--------------x
| 1 | 2014-01-11 | 2014-01-13 |
| 1 | 2014-02-23 | 2014-02-27 |
| 2 | 2014-05-06 | 2014-05-30 |
| 3 | NULL | NULL |
x------x-------------x--------------x
Khi bạn sử dụng UNPIVOT mang FROMDATE VÀ TODATE thành một cột, nó sẽ loại bỏ NULL giá trị theo mặc định.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
tạo ra kết quả dưới đây. Lưu ý rằng chúng tôi đã bỏ sót bản ghi của Id số 3
x------x-------------x
| Id | DATES |
x------x-------------x
| 1 | 2014-01-11 |
| 1 | 2014-01-13 |
| 1 | 2014-02-23 |
| 1 | 2014-02-27 |
| 2 | 2014-05-06 |
| 2 | 2014-05-30 |
x------x-------------x
Trong những trường hợp như vậy, một APPLY có thể được sử dụng (CROSS APPLY hoặc OUTER APPLY , có thể hoán đổi cho nhau).
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
tạo thành kết quả sau và giữ lại Id trong đó giá trị của nó là 3
x------x-------------x
| Id | DATES |
x------x-------------x
| 1 | 2014-01-11 |
| 1 | 2014-01-13 |
| 1 | 2014-02-23 |
| 1 | 2014-02-27 |
| 2 | 2014-05-06 |
| 2 | 2014-05-30 |
| 3 | NULL |
x------x-------------x