Aysegul KARA

             Sayı tablosu kullanarak geliştirilen çözümler:

 Merhaba,TSQL de string ayrıştırma işlemleri ve sahte dizi kullanımı ile ilgili makalemizin bu bölümünde ayrıştırma işlemleri için gerekli olan sayı tablomuzu nasıl oluşturacağımızı anlatacağım. Daha büyük stringlerle çoğu durumda, ardışık olarak artan bir sayı tablosu kullanmak genellikle başvurulan daha hızlı çözümlerden biridir. Ne var ki test yapmadan, genel performans iddiaları şüphe götürmeli. Neredeyse bir metodun diğerinden iyi olduğuna karar vermek imkânsız. Sayı tablosu kullanarak çeşitli çözümlerini incelemeden önce, sayı tablosu oluşturmanın yöntemlerini inceleyeceğiz.

 TSQL ile ardışık artan bir sayı tablosu oluşturma:

            Düzenli olarak artan bir sayı tablosu oluşturmanın çeşitli yolları vardır. Bir sayı tablosu oluşturabilen ya temel bir tablo ya bir view ya da herhangi bir özel ifade bu senaryoların içinde kullanılabilir.Sayı tablosu oluşturmaya yarayan genel methodlardan bazıları gelecek bölümde detaylı bir şekilde anlatılacak. Ardışık artan değerler bir query in parçası olarak üretilebilir olmasına rağmen, genel olarak temel kalıcı bir tablo oluşturulması ve çeşitli çözümler için ihtiyaç duyulan sayıların eklenmesi önerilir. Muhtemel mükerrer kayıtları önlemek için sayı eklenen columun da Primary Key olarak kullanılmalı.

Kimlik tabanlı sayı numarası ile ardışık tablolar oluşturmak için tablonun içindeki bir tanım columunu için default değerler vererek kullanma basitçe bir yöntem olabilir. Bu yaklaşımda bir başka önemli kısım ise sadece kalıcı tablolar ile kullanılıyor olabilmesi. Herhangi bir belirtme olmadan IDENTITY özelliği her başlangıç ve artış için default olarak 1 değerini kullanır.

    CREATE TABLE dbo.Sayi(n INT NOT NULL IDENTITY) ;
    GO
    SET NOCOUNT ON ;
    INSERT dbo.Sayi DEFAULT VALUES ;
    WHILE SCOPE_IDENTITY() < 500
        INSERT dbo.Sayi DEFAULT VALUES ;

IDENTITY() fonksiyonu ile SELECT INTO herhangi bir var olan tablodan yeni bir tabloya data aktarmak için kullanabiliriz.  Örnek bir CROSS JOIN inin var olan iki tablo arasında kullanımını gösteriyor.

SELECT TOP 500 IDENTITY(INT) AS n

      INTO dbo.Sayi

      FROM Northwind.dbo.Orders o1

     CROSS JOIN Northwind.dbo.Orders o2; 

While kullanarak düzenli döngüler:

Burada basit döngü bir anda tek satır ekleyen bir döngü

CREATE TABLE dbo.Sayi(n INT NOT NULL PRIMARY KEY) ;
    GO
    SET NOCOUNT ON
    DECLARE @Index INT ;
    SET @Index = 1 ;
    WHILE @Index <= 500 BEGIN
        INSERT dbo.Sayi (n) VALUES (@Index) ;
        SET @Index = @Index + 1 ;
    END

 Yukarıdaki döngünün verimliliği aşağıdaki gibi kullanımlarla arttırılabilir

    SET NOCOUNT ON
    DECLARE @Index AS INT;
    SET @Index = 1

    INSERT dbo.Sayi SELECT 1;
    WHILE @Index * 2 < 500 BEGIN
        INSERT dbo.Sayi
        SELECT @Index + n
          FROM dbo.Sayi
        SET @Index = @Index + @@ROWCOUNT
    END

**************************************************************************
    INSERT dbo.Sayi

    SELECT @Index + n
      FROM dbo.Sayi
     WHERE @Index + n <= 500

 

 

Merhabalar, TSQL de string ayrıştırma işlemleri ve sahte dizi kullanımı yazı dizimize kaldığımız yerden devam ediyoruz. Bütün örnekler için aşağıdaki tanımı kullanacağız.

DECLARE @p VARCHAR(50)
SET @p = ‘ALFKI, LILAS, PERIC, HUNGC, SAVEA, SPLIR, LONEP, GROSR’

PATINDEX() ile doku eşleştirmesini kullanma:             Bir dokunun kelime içindeki ilk görüldüğü yerdeki pozisyonunu döndürür. Eğer yoksa sıfır döndürür.

PATINDEX ( ‘%pattern%’ , expression )

    SELECT CustomerID, ContactName, CompanyName
      FROM Northwind.dbo.Customers
     WHERE PATINDEX( ‘%,’ + CustomerID + ‘,%’, ‘,’ + @p + ‘,’ ) > 0   ; 
 

LIKE operatoru ile doku eşleştirmesini kullanma:

    SELECT CustomerID, ContactName, CompanyName
      FROM Northwind.dbo.Customers
     WHERE ‘,’ + @p + ‘,’ LIKE ‘%,’ + CustomerID + ‘,%’ ; 

String Ayrıştırma:

            Bazı koşullarda, parsed listesini sonraki işlerde kullanılabilen (örneğin bir IN clause ile birlikte)  bir resultset olarak kullanmak isteyebilirsin. Daha büyük liste örnekleri için IN() clause kullanmaktansa JOIN kullanmak daha etkili olabilir. Ayrıştırma işlemleri için kullanılan fonksiyonları ve yöntemleri incelemeye başlayacağız.     

PARSENAME() fonksiyonunu kullanma:Bir object isminin işaret edilen kısmını döndürür.PARSENAME ( ‘object_name’ , object_piece )

            Parsename() foksiyonu bir sysname değeri döndürür (nvarchar(128)’ e eşdeğer)  ve genel olarak database nesnelerin nesne adı, owner name, database name ve server name gibi database nesnesinin tanımlayıcı kısımlarını elde etmek için kullanılır. Bununla birlikte eğer string 5 ayrılmış değerden az yaratılmış ise bir string parse etmek içinde kullanılabilir. Bu konuyla ilgili tipik senaryolar full name ve bir IP adresinin tanım kısmını ayırmak gibi örnekler olacak. Aşağıda bir stringi ayrıştırmak için kullanılmıştır.

Örneğin:

DECLARE @ad NVARCHAR(500)

SET @ad = N’Kara, Dr.Murat, Can’

SELECT PARSENAME(ad, 3) AS “Unvan”,

PARSENAME(ad, 2) AS “Ad”,

PARSENAME(ad, 1) AS “Ikinci Ad”,

PARSENAME(ad, 4) AS “Soyad”    FROM ( SELECT REPLACE(@ad, ‘, ‘, ‘.’)) D(ad)

TSQL de birbirinden virgülle ayrılmış string listelerini ayrıştırmak arada sırada ihtiyaç duyduğumuz bir kullanım şeklidir. Normal koşullarda, ilişkili database modelinde böyle bir durum ile karşılaşılmaz.

Bazen Sql programcıları çift değerli sütün yâda değişken kullanma gereksinimi ile karşı karşıya kalırlar( genelliklede veri başka bir yerden geldiğinde). TSql de liste ya da dizi tiplerini destekleyen yerleşik bir yapı olmadığı için, çift değerleri bir araya getirmek de genellikle delimited VARCHAR strings kullanılır. İlişkideki bir öznitelik sadece süzülmüş uygun bir tipe sahip olabildiğinden beri hepimizin bildiği gibi çift değerleri tek bir sütunda tutmak ilişkili modelin temel kuralıdır.

SQL tabloları doğası gereği çift değerli sütunlara izin vermez. Bu XML veri tipleri ortaya çıkmadan önce mantıklı bir yapı idi. Programcılar ara sıra değişen başarı dereceleri ile bu kuralı eziyorlardı. Kullanıcılar daima virgül ya da boşluk gibi bir karakterle ayrılmış daha küçük stringlerin bir kombinasyonu olan tek bir string yorumlamak zorunda kalabilirler. Programcılar bu nedenle, var olan string fonksiyonlarının gücünden faydalanarak, birleştirilmiş stringlerden istediği kadar küçük parçaları söküp çıkartabilirler.

Burada önerilen methodlar sadece eksiliği gidermek için kullanılmalı, üretim sistemleri için önerilmez. Eğer ürün kılavuzunda dökümanta edilmemiş bir method kullanıyorsan, onları doğruca ikaz et ve konu ile ilgili bütün uyarıları yapın.

Göz önüne alınması gerekenler:

Bir diziyi parse eden ve veri yönetimi sağlayan çoğu method veriyi tabloya çift satırmış gibi eklemek için kullanılabilir. Sonraki kısımda anlatılacaklar: bir kullanma şekli tanımlamak ve bir değişkende, parametrede ya da hatta column değeri gibi tanımlanan stringdeki altbölümleri bir tabloya kaydetmek. Örnekler virgülle ayrılmış listelerdir.Genel olarak bilinen değerleri   ‘item- 1,item-2,item-3….item-n’ olan CSV Gibi.

Pratikte, stringleri ayırmak için herhangi bir karakteri kullanabilirsin space de dahil olmak üzere methodları karaktere göre uyarlayabilirsin. Aşağıdaki örnekte, Northwind database inde Customer tablosundan rastgele birkaç müşteri tanımı seçilmiş. Aşağıdaki her bir örnek için bu listeyi kullanacağız.

DECLARE @p VARCHAR(50)
SET @p = ‘ALFKI, LILAS, PERIC, HUNGC, SAVEA, SPLIR, LONEP, GROSR’

Direk Data karşılaştırması:

Basit karşılaştırmalar için, karmaşık alışılmış kullanımlara gerek yok. TSQL içinde içsel eşleştirme kalıplarını içeren özellikler çoğu koşulda direk olarak kullanılabilir.

Bir ilk olarak örnek değerler listesinden seçmek ve onu WHERE koşulundaki IN listesinde kullanmak. Aşağıda bazı genel methodlar:

CHARINDEX() fonksiyonunu kullanma:

Expression2 içinde expression1 arar ve eğer bulursa başlangıç pozisyonunu döndürür. Arama start_location dan başlar.

CHARINDEX ( expression1, expression2 [ , start_location ] )

SELECT CustomerID, ContactName, CompanyName
FROM Northwind.dbo.Customers
WHERE CHARINDEX( ‘,’ + CustomerID + ‘,’, ‘,’ + @p + ‘,’ ) > 0 ;

CustomerID ContactName                    CompanyName
———- —————————— ——————————
ALFKI      Maria Anders                   Alfreds Futterkiste
GROSR      Manuel Pereira                 GROSELLA-Restaurante
HUNGC      Yoshi Latimer                  Hungry Coyote Import Store
LILAS      Carlos González                LILA-Supermercado
LONEP      Fran Wilson                    Lonesome Pine Restaurant
PERIC      Guillermo Fernández            Pericles Comidas clásicas
SAVEA      Jose Pavarotti                 Save-a-lot Markets
SPLIR      Art Braunschweiger             Split Rail Beer & Ale

 

SQL Server 2005 Transact-SQL sonuç kümende sıralama yapmanı sağlayacak  fonksiyonlar içerir. Bu fonksiyonlardan bir veya daha fazlasını sorgunuzun SELECT cümleciğine eklediğinizde, kullandığınız fonksiyona göre  her satır için bir sıralama atamış olursunuz.

T-SQL şimdilik 4 tane sıralama fonksiyonu içerir : ROW_NUMBER, RANK, DENSE_RANK ve NTILE. Şimdi kısaca bu fonksiyonların tanımı yapacak ve nasıl çalıştıklarını göstereceğim.

Sıralama Fonksiyonlarının  Genel  Yazımı:

ROW_NUMBER ( ) ,RANK(),DENSE_RANK(),NTILE()    OVER ( [ <partition_by_clause> ] <order_by_clause> )

 

<partition_by_clause>

FROM cümleciği tarafından üretilen sonuç kümelerinde, sıralama fonksiyonunun uygulanacağı bölümleri  belirler.

<order_by_clause>

ORDER BY bir bölüm içindeki sıralamanın hangi sütuna göre yapılacağını belirler.

 

DECLARE @Tablo Table

(ID int identity,  SoyAd varchar(100),SatisPayi int,Ay varchar(30),Yil int)

 

insert into @Tablo values(‘A’,280000,‘Ocak’,2002)

insert into @Tablo values(‘B’,280000,‘Ocak’,2004)

insert into @Tablo values(‘A’,267000,‘Nisan’,2002)

insert into @Tablo values(‘B’,266000,‘Ocak’,2002)

insert into @Tablo values(‘C’,264000,‘Ocak’,2002)

insert into @Tablo values(‘D’,263000,‘Haziran’,2003)

insert into @Tablo values(‘E’,247000,‘Nisan’,2003)

insert into @Tablo values(‘B’,244000,‘Haziran’,2001)

insert into @Tablo values(‘B’,239000,‘Ocak’,2003)

insert into @Tablo values(‘B’,244000,‘Haziran’,2001)

insert into @Tablo values(‘A’,234000,‘Ocak’,2004)

insert into @Tablo values(‘C’,226000,‘Aralýk’,2002)

insert into @Tablo values(‘A’,226000,‘Haziran’,2001)

insert into @Tablo values(‘C’,224000,‘Nisan’,2003)

insert into @Tablo values(‘F’,217000,‘Ocak’,2003)

insert into @Tablo values(‘C’,210000,‘Haziran’,2002)

 

 

 

SELECT

ROW_NUMBER() OVER(ORDER BY SatisPayi DESC) AS [RowNumber],

RANK() OVER(ORDER BY SatisPayi DESC) AS [Rank],

DENSE_RANK() OVER(ORDER BY SatisPayi DESC) AS [DenseRank],

NTILE(5) OVER(ORDER BY SatisPayi DESC) AS [NTile],

SoyAd, SatisPayi, Ay, Yil

FROM @Tablo

 

Örneğimizideki Select deyiminde 4 sıralama fonksiyonunu kullanmakta.Bütün fonksiyonları tek deyimin içine dahil ettim.Böylece her fonksiyonun döndürdüğü sonucu karşılaştırabilirsiniz.

 

 

 

 

 

 

 

 

[RowNumber]

pan style="color: black">[Rank]

[DenseRank]

[NTile]

SoyAd

SatisPayi

Ay

Yil

1

1

1

1

C

264000

Ocak

2002

2

1

1

1

C

226000

Aralık

2002

3

1

1

1

C

224000

Nisan

2003

4

4

2

2

F

217000

Ocak

2003

5

5

3

2

B

280000

Ocak

2004

6

5

3

2

B

266000

Ocak

2002

7

5

3

3

B

244000

Haziran

2001

8

5

3

3

B

239000

Ocak

2003

9

5

3

3

B

244000

Haziran

2001

10

10

4

4

E

247000

Nisan

2003

11

11

5

4

D

263000

Haziran

2003

12

12

6

4

A

226000

Haziran

2001

13

12

6

5

A

234000

Ocak

2004

14

12

6

5

A

280000

Ocak

2002

15

12

6

5

A

267000

Nisan

2002

 

ROW_NUMBER () fonksiyonu

ROW_NUMBER()  fonksiyonu sıralama fonksiyonlarının en kolayıdır. Sizinde sonuç kümesinden görebildiğiniz gibi satırın numarasıdır. Bir satırın bir sonuç kümesinin bir bölümündeki ardışık numarasını döndürür. Her bölüm için ilk satır 1 ile başlar.  Ben bu örnekte SatisPayi sütununa göre sıralama yapıyorum(azalan sırada). Dönen sonuç kümesinde sonuçlar en yüksek SatisPayindan başlıyor.

RANK()  function in SQL Server

Listemdeki diğer sıralama fonksiyonu RANK(). Rank fonksiyonunu kullanıldığı zaman sıralama yaptığın sütundaki aynı değerler aynı sıralama numarasını alacaktır. Fakat sıralama değeri sonuç kümesindeki satırın pozisyonunu baz alır. Örneğin,Üçüncü sıradaki SatisPayi  267,000 en yüksek ikinci değer. Fakat 2.sıra yerine 3 üncü sıraya düşmektedir. RANK fonksiyonu 2 yi atladı çünkü ikinci satır birinci satırla eşleşiyordu. Eğer 4 üncü satırda 3.üncü satırla aynı değeri paylaşsa idi 3 ile sıralanacaktı.

 
   
 

DENSE_RANK()  function

DENSE_RANK  function da, RANK function gibi aynı değerli  sütunlar aynı sıralama değerini alırlar ama ardışık olarak artar. Sonuç kümesinde de görüldüğü gibi 3. Satır 2 sıralama numarasını almıştır çünkü 2. en yüksek SatişPayina sahiptir.

 ROW_NUMBER, RANK ve DENSE_RANK fonksiyonları sonuçları döndürüş türüne göre benzerdir. Fark numaralandırmanın sıralı olup olmadığında ve satıra bağlı olup olmadığındadır. NTILE fonksiyonu üç fonksiyondan farklıdır.

NTILE()  function

NTILE fonksiyonunu kullandığında parametre olarak bir integer vermelisin. NTILE sonuç kümesini verilen parametreye göre böler. Örneğineğimizde parametre olarak 5 verdim. Bu demek ki sonuç 5 grupa bölünecek. 15 satır olduğu için her grup 3 satır içerecek. Gruplar Satis Payina göre değer alacak. En yüksek satis payina sahip 3 satır 1 değerini diğer en yüksek Satis payi 2 değerini alır. Çünkü 5 grup var.

Sizinde gördüğünüz gibi, SQL Serverdaki sıralama fonksiyonları gayet açık. Genelde Matrix raporlarda satır numarası kullanırken çok işime yarıyor.   

© 2010 bilyaz.com , Programlama Makaleleri, Yazılım Makaleleri , Örnek Kodlar , Eğitim Videoları , C#,ASP.NET,SQL,PHP Suffusion WordPress theme by Sayontan Sinha