Kaçınamayacağınız CROSS APPLY
veya kaçınamayacağınız çeşitli durumlar vardır OUTER APPLY
.
İki masanız olduğunu düşünün.
MASTER TABLO
x------x--------------------x
| Id | Name |
x------x--------------------x
| 1 | A |
| 2 | B |
| 3 | C |
x------x--------------------x
DETAY TABLOSU
x------x--------------------x-------x
| Id | PERIOD | QTY |
x------x--------------------x-------x
| 1 | 2014-01-13 | 10 |
| 1 | 2014-01-11 | 15 |
| 1 | 2014-01-12 | 20 |
| 2 | 2014-01-06 | 30 |
| 2 | 2014-01-08 | 40 |
x------x--------------------x-------x
ÇAPRAZ UYGULAMA
Değiştirmemiz gereken birçok durum INNER JOIN
var CROSS APPLY
.
1. TOP n
Sonuçlarda INNER JOIN
işlevselliğe sahip 2 tabloyu birleştirmek istiyorsak
Biz belirlemeniz gerekirse düşünün Id
ve Name
gelen Master
biri için ve son iki tarihleri Id
arasından Details table
.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
INNER JOIN
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID
Yukarıdaki sorgu aşağıdaki sonucu verir.
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 |
x------x---------x--------------x-------x
Bakın, son iki tarih için son iki tarih için sonuçlar üretti Id
ve sonra bu kayıtları sadece dış sorguda birleştirdi Id
, ki bu yanlış. Bunu başarmak için kullanmamız gerekiyor CROSS APPLY
.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
CROSS APPLY
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
WHERE M.ID=D.ID
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ve takip eden sonucu oluşturur.
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 |
x------x---------x--------------x-------x
İşte çalışma. İçerideki sorgu CROSS APPLY
, INNER JOIN
bunu yapamayan dış tabloya başvurabilir (derleme hatası verir). Son iki tarihi bulurken, birleştirme CROSS APPLY
yani içinde yapılır WHERE M.ID=D.ID
.
2. INNER JOIN
İşlevleri kullanarak işlevselliğe ihtiyaç duyduğumuzda .
CROSS APPLY
tablo ve INNER JOIN
a'dan sonuç almamız gerektiğinde yerine kullanılabilir .Master
function
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
CROSS APPLY dbo.FnGetQty(M.ID) C
Ve işte fonksiyon
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE ID=@Id
)
aşağıdaki sonucu oluşturan
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 |
x------x---------x--------------x-------x
DIŞ UYGULAMA
1. TOP n
Sonuçlarda LEFT JOIN
işlevselliğe sahip 2 tabloyu birleştirmek istiyorsak
Tablodaki Master
her bir Id için başlangıç ve son iki tarihi seçmemiz gerekip gerekmediğini düşünün Details
.
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
aşağıdaki sonucu oluşturan
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
Bu yanlış sonuçlar getirecektir, yani biz katılmış olsak da Details
tablodan en son iki tarih verisini getirecektir . Yani doğru çözüm kullanmaktır .Id
Id
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
aşağıdaki istenen sonucu oluşturan
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. LEFT JOIN
Kullanarak işlevselliğe ihtiyacımız olduğunda functions
.
OUTER APPLY
tablo ve LEFT JOIN
a'dan sonuç almamız gerektiğinde yerine kullanılabilir .Master
function
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Ve fonksiyon buraya gelir.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE ID=@Id
)
aşağıdaki sonucu oluşturan
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
Ortak özelliği CROSS APPLY
veOUTER APPLY
CROSS APPLY
veya birbirinin yerine geçebilen değerleri döndürürken OUTER APPLY
korumak için kullanılabilir NULL
.
Aşağıdaki tabloya sahip olduğunuzu düşünün
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
Kullandığınızda UNPIVOT
getirmek FROMDATE
VE TODATE
tek sütuna, bu ortadan kaldıracak NULL
varsayılan olarak değerleri.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
aşağıdaki sonucu oluşturur. Rekor Id
sayıları kaçırdığımızı unutmayın3
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
Bu gibi durumlarda a CROSS APPLY
veya OUTER APPLY
yararlı olacaktır
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
aşağıdaki sonucu oluşturan Id
ve değerini olduğu yerde tutan3
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