UNION ve UNION ALL ifadeleri iki sorgu sonucunun birleştirilmesi için kullanılır. Tek farkı, UNION mükerrer kayıtları getirmez, UNION ALL ise tüm kayıtları olduğu gibi listeler. Önceki yazıda her grubun ilk kayıt edilmiş 2 ürününü UNION yöntemiyle getirmiştik. Aynı yöntemi kullananarak her grubun son kayıt edilmiş 2 ürünü alacağız. Bunun için aklımıza ilk gelen query şudur; tablodaki kayıtları UrunId’ye göre büyükten küçüğe sıralayıp TOP 1 ile en üsttekini almaktır. Tablomuzu tekrar gözden geçirelim. .
GrupId | GrupAd |
---|---|
1 | G1 |
2 | G2 |
UrunId | UrunAd | GrupId | Stok |
---|---|---|---|
1 | P1 | 1 | 4 |
2 | P2 | 2 | 6 |
3 | P3 | 1 | 7 |
4 | P4 | 2 | 0 |
5 | P5 | 2 | 1 |
6 | P6 | 1 | 3 |
SELECT TOP 2 UrunId,UrunAd FROM Urun WHERE GrupId=1 ORDER BY UrunId DESC UNION SELECT TOP 2 UrunId,UrunAd FROM Urun WHERE GrupId=2 ORDER BY UrunId DESC
Burada, SQL Server’in UNION ve ORDER BY’in iç içe kullanılamayacağını anlatan hatasıyla karşılırız.Incorrect syntax near the keyword ‘UNION’. UNION ile ifadeleri birleştirdiğimizde sadece en alt querynin dibinde ORDER BY kullanabiliriz.
SELECT TOP 2 GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=1 UNION SELECT TOP 2 GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=2 ORDER BY UrunId DESC
Fakat bu durumda her SELECT sonucu ayrı ayrı değil bir bütün olarak ASC veya DESC olarak sıralanır.
GrupId | UrunId | UrunAd |
---|---|---|
2 | 4 | P4 |
1 | 3 | P3 |
2 | 2 | P2 |
1 | 1 | P1 |
Oysa biz, her SELECT’in bağımsız olarak büyükten küçüğe sıralanmasını istiyoruz. Bu hatayı aşmak için asıl querymizi türemiş bir tablo(derived tables) olarak kullanacağız.
SELECT * FROM( SELECT TOP 2 GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=1 ORDER BY UrunId DESC ) AS T UNION SELECT * FROM ( SELECT TOP 2 GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=2 ORDER BY UrunId DESC ) AS T
GrupId | UrunId | UrunAd |
---|---|---|
1 | 3 | P3 |
1 | 6 | P6 |
2 | 4 | P4 |
3 | 5 | P5 |
UNION ve ORDER BY birlikte kullanıldığı zaman ORDER BY edilmiş kolonun SELECT içerisinde de listelenmesi gerekir. Aynı query mantığını kullanarak her ürün gruptan rasgele iki ürün getirelim. Her defasında farklı kayıtların gelmesi için NEWID() fonksiyonu kullanılır. Bu fonksiyon, her satıra farklı bir GUID değeri verir.
SELECT * FROM( SELECT TOP 2 NEWID() RowId,GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=1 ORDER BY NEWID() ) AS T UNION SELECT * FROM ( SELECT TOP 2 NEWID() RowId,GrupId,UrunId,UrunAd FROM Urun WHERE GrupId=2 ORDER BY NEWID() ) AS T
sizin bu çözüm top kullanınca geçerli. tümü listelenmeye kalkınca çakıyor.The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
Bilal bey,haklısınız eğer TOP kullanılmazsa hata alınır. Fakat mantıklı olan da bu değli mi zaten. Yani burada TOP ifadesini kaldırdığımızda o zaman hem kötü bir query hem de amacının dışına çıkmış olmaz mı. Çünkü bu durumda aslında tüm Urun tablosunu sorgulamış olacağız o zaman da subquery kullanmaya gerek kalmaz diye düşünüyorum. Bu durumda aşağıdaki yapıyı kullanmak daha mantıklı olacaktır.
SELECT GrupId,UrunId,UrunAd FROM Urun1
Ama yine de makaledeki subquery yapısını kullanmak gerekiyorsa o zaman “TOP 100 PERCENT” kullanarak bu işi çözebiliriz. Çünkü execution plan’da “TOP 100 PERCENT” etkisiz eleman gibi çalışır yani performans kaybı yaşatmaz.Ayrıca TOP yapmadan grupları kendi içerisinde sıralamak istersek SQL 2005’teki Ranking Function’lar işimizi görebilir.WHERE GrupId=1
UNION
SELECT GrupId,UrunId,UrunAd FROM Urun1
WHERE GrupId=2
Teşekkürler Ahmet Bey, çok işime yaradı.
Saygılar,
ahmet hocam merhaba;
ben bu unınon all komutunu ikikez nasıl kullanırım acaba
çünkü tek tablom var ve üç adet de sutun bu sutunların her birini ayrı ayrı sorgulayacağım için unuıno 3 kez kullanmam gerekli ne yapmalıyım.
Aşağıdaki örnekte olduğu gibi SELECT sorguları arasında istediğiniz kadar UNION veya UNION ALL kullanabilirsiniz.
SELECT Kolonlar FROM Tablo WHERE Kolon=1
UNION ALL
SELECT Kolonlar FROM Tablo WHERE Kolon=1
UNION ALL
SELECT Kolonlar FROM Tablo WHERE Kolon=1
UNION ALL
SELECT Kolonlar FROM Tablo WHERE Kolon=1
. . .
Burada dikkat edilmesi gereken konu her sorgunun aynı sayıda ve tipte kolon döndürmesindir. Bu arada eğer yanlış anlamadıysam aynı tabloda farklı kolonlar üzerinde sorgu yapıp tek bir kayıt dizisi döndürmek istiyorsun. Bunun için neden UNION kullanmak istediğini anlamadım.
Ahmet Bey öncelikle emeğinize sağlık.En son örneğinizde select sorgularının bağımsız davrandığı durumda sorgu sonucunu yanlış yazmamış mısınız.