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 [email protected]
)
đã 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