Birbirleriyle ilişkili iki tablo düşünelim. Birinci tabloda başlık bilgileri ikinci tabloda ise bu başlığa ait detayların bulunduğunu varsayarak her başlıktan n tane detay kaydını getirmek için nasıl bir query yazmamız gerekir. Özellikle haber sitelerinin anasayfalarında her gruptan belli kriterlere uygun n kayıt getirmek veya yüksek stoklu ürün gruplarının en yüksek stoklu n tane ürününü listelemek için bu tür pratik querylere ihtiyaç duyarız.
Bu türden bir query oluşturmak için örnek olarak Grup ve Urun şeklinde iki tane tablo oluşturalım.
CREATE TABLE [dbo].[Grup] ( [GrupId] [int] IDENTITY (1, 1) NOT NULL , [GrupAd] [char] (10) NULL ) ON [PRIMARY] GO CREATE TABLE [dbo].[Urun] ( [UrunId] [int] IDENTITY (1, 1) NOT NULL , [UrunAd] [char] (10) NULL , [GrupId] [int] NULL , [Stok] [int] NULL ) ON [PRIMARY]
Birinci tabloda ürün grupları, ikinci tabloda ise ürün bilgileri ve stok adetleri bulunmaktadır. Örnek olarak aşağıdaki kayıtları girelim.
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 |
Bu veriler doğrultusunda aşağıdaki işlemleri yapalım;
Her grubun ilk veya ürününü okumak.
Gruplara ait ilk veya son ürünü okumak veya stoğu en fazla veya en düşük olan ürünleri okumak için UrunId veya Stok tutarlarından yararlanılır. Bu tür sorgularda sub query kullanılır. İç query’de Urun tablosunu GrupId’ye göre gruplayıp o gruba ait ilk veya son ürünü bulunur vey o ürünlere ait ID üzerinden ürünlerin bilgilerine erişilir.
SELECT U.GrupId,UrunId,UrunAd,Stok FROM Urun U INNER JOIN ( SELECT GrupId,MIN(UrunId) as MinUrunId FROM Urun GROUP BY GrupId ) as T ON U.GrupId=T.GrupId AND U.UrunId=T.MinUrunId
GrupId | UrunId | UrunAd | Stok |
---|---|---|---|
1 | 1 | P1 | 4 |
2 | 2 | P2 | 6 |
Yine aynı şekilde en büyük ürünleri de bulabiliriz.
SELECT U.GrupId,UrunId,UrunAd,Stok FROM Urun U INNER JOIN ( SELECT GrupId,MAX(UrunId) as MaxUrunId FROM Urun GROUP BY GrupId ) as T ON U.GrupId=T.GrupId AND U.UrunId=T.MaxUrunId
Her grubun ilk 2 ürününü getirelim.
Bunun önceki query’den farkı birden fazla ürünün isteniyor olmasıdır. Bilindiği Max veya MIN gibi grupsal fonksiyonlar, tek kayıt döndürür. Bu tür işlemleri kolayca yapabilmek için satırları numaralandırmak gerekir. Bunun için tablodaki IDENTITY olan UrunId kolonundan yararlanacağız. Bu numarayı kullanarak tabloyu kendisiyle JOIN edeceğiz. Burada her grubun ilk 2 kaydını getireceğimiz için her ürünü ele alıp o üründen önce kaç kayıt olup olmadığını sorgulayacağız. Kendisinden önce en fazla 2 kayıt olan ürünleri getireceğiz. Böylece o gruptaki ilk 2 kayıt gelmiş olur.
SELECT U1.GrupId,GrupAd,UrunId,UrunAd,Stok FROM Urun U1 INNER JOIN Grup G ON U1.GrupId=G.GrupId WHERE (SELECT COUNT(*) FROM Urun AS U2 WHERE U2.GrupId = U1.GrupId AND U2.UrunId<U1.UrunId) < 2 ORDER BY G.GrupAd
GrupId | GrupAd | UrunId | UrunAd | Stok |
---|---|---|---|---|
1 | G1 | 1 | P1 | 4 |
1 | G1 | 3 | P3 | 7 |
2 | G2 | 2 | P2 | 6 |
2 | G2 | 4 | P4 | 0 |
Her grubun stoğu bulunan ilk 2 ürününü getirelim.
Yukarıdaki query’e stok koşulunu da ekleyeceğiz. Bu koşulu hem içerdeki query hem de dış query’e ekleyerek doğru sonuca varırız. Eğer sadece dış query’e yazarsak ilk 2 kayıt içerisinde stoğu 0 olan kayıt olduğu için(UrunId=4) 2 nolu grubtan tek kayıt gelecektr. Sadece iç query’e yazarsak bu sefer 2.gruba ait hem 4 hem de 5 nolu ürün gelecektir. 5 nolu ürün gelir çünkü gerçekten de kendisinde önce stoğu>0 olan 2 kayıt var. Bu iki sıkıntıyı aşmak için her iki tarafa da stok koşulunu ekleyeceğiz.
SELECT U1.GrupId,GrupAd,UrunId,UrunAd,Stok FROM Urun U1 INNER JOIN Grup G ON U1.GrupId=G.GrupId WHERE (SELECT COUNT(*) FROM Urun AS U2 WHERE U2.GrupId = U1.GrupId AND U2.UrunId<U1.UrunId AND U2.Stok < 0
GrupId | GrupAd | UrunId | UrunAd | Stok |
---|---|---|---|---|
1 | G1 | 1 | P1 | 4 |
2 | G2 | 2 | P2 | 6 |
1 | G1 | 3 | P3 | 7 |
2 | G2 | 5 | P5 | 1 |
Her grubun son 2 ürününü listeleyelim.
Her grubun en son kayıt edilmiş 2 ürününü getirelim. En son kayıt edilmiş ürünler, UrunId’leri en yüksek olarak ürünlerdir. Yine aynı şekilde yukarıdaki queryleri kullanacağız. Tek farkı, ürünleri sorgularken üründen sonra kayıt edilmiş ürünleri listeleyeceğiz.
SELECT U1.GrupId,GrupAd,UrunId,UrunAd,Stok FROM Urun U1 INNER JOIN Grup G ON U1.GrupId=G.GrupId WHERE (SELECT COUNT(*) FROM Urun AS U2 WHERE U2.GrupId = U1.GrupId AND U2.UrunId
Her grubun son 2 ürününü listeleyelim.
Bu yazıda geliştirdiğimiz queryleri basit haliyle UNION ifadesiyle de yapabiliriz. Fakat bunun için her SELECT cümlesini manual oluşturmamız gerekir. Örneğin her grubun ilk 2 ürününü listeyelim.
SELECT TOP 2 UrunId,UrunAd FROM Urun WHERE GrupId=1 UNION SELECT TOP 2 UrunId,UrunAd FROM Urun WHERE GrupId=2
burada görüldüğü gibi yeni bir grup eklendiğinde UNION ifadesiyle yeni bir SELECT satırı eklemek gerekir. Peki UNION ile her grubun en son iki ürününü nasıl okuruz. Bunun örneğini bir sonraki yazıda yapalım.
vallahi ben bu oyunu sevdim ne deseniz ben bu oyunu iyi buldum ne yazıkki sevmeyenler de var
Merhabalar
“Her grubun ilk 2 ürününü getirelim.” kısmındaki örnek kod bölümünde html ve sql kodları içe içe geçmiş durumda olduğundan konuyu algılayamadım düzeltmenizi rica ediyorum. Ayrıca diğer vermiş olduğunuz bilgilerden çok faydalandım sonsuz teşekkürler.
Merhabalar;
“Her grubun ilk 2 ürününü getirelim” ve diğerlerinde maalesef kodlar yarım olduğundan okunamıyor. Rica etsem tam okunabilir halini gösterebilir misiniz?
Taner Bey, sorguları düzelttim.