SQL Server UNION / UNION ALL ile birlikte ORDER BY kullanmak

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

SQL Server UNION / UNION ALL ile birlikte ORDER BY kullanmak” üzerine bir düşünce

  1. bilal

    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.

    Cevapla
  2. Ahmet Kaymaz Yazar

    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
    WHERE GrupId=1
    UNION
    SELECT GrupId,UrunId,UrunAd FROM Urun1
    WHERE GrupId=2
    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.

    Cevapla
  3. UNSAL OSMA

    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.

    Cevapla
  4. Ahmet Kaymaz Yazar

    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.

    Cevapla
  5. Onur

    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.

    Cevapla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.