MSSQL Liste İçinde Liste Arama İşlemi

  • 22.10.2015
  • M.Tayyip Yetiş
  • MSSQL

mssql logoMerhaba arkadaşlar, MSSQL ile çalışırken zaman zaman veritabanı mimarisine göre en kısa, hızlı ve pratik sorgular yazmak isteriz çünkü bu üç kural veritabanı sorguları için vazgeçilmezdir özellikle hız en önemli faktördür zira sql ile bir sorgudaki cümlelerin yerinin değiştirilmesi bile hız açısından büyük farklara yol açabilir bu da istenmeyen bir durumdur. Bu makalede benim karşılaştığım bir problem için kendim geliştirdiğim bir fonksiyonu paylaşacağım, problem şöyle ki;

örneğin elimizde üyelerimizin tutulduğu bir uyeler tablosu ve spor dallarının tutulduğu sporlar tablomuz var. Biz hangi üyenin hangi sporla uğraştığını tutmak istiyoruz bunun için ilk yöntem uye_sporlar isminde yeni bir tablo oluşturup uye_id ve spor_id değerleri ile çoktan-çok tablo ilişkisi kurmaktır genelde kullanılan da budur ve listeleme filtreleme gibi işlemleri yaparken de left join ya da cross apply gibi ifadeler kullanarak tablolar birleştirilir ve sorgular yazılır. Diğer bir yöntem ise; uyeler tablosunda uye_sporlar isminde bir sütun açmak ve bu sütunda seçilen sporların id değerini yada metin değerini virgül(ya da herhangi bir belirteç) ile ayırarak kaydetmek ve aşağıda paylaştığım fonksiyon ile bu sütunda en az bir tane var mı mantığı ile sorgulama yapmak.

Daha iyi açıklamak gerekirse; uye_sporlar sütununda “basketbol,futbol,tenis,satranç” şeklinde bir değerimiz var bunlar isim değil de ID de olabilir farketmez. Biz filtreleme ya da arama sayfamızda checkbox kontrolü ile seçilen sporlardan en az bir tanesini kaydetmiş olan üyeleri listelemek istiyoruz bu demek oluyor ki bize “tenis,satranç,boks”, “satranç,tenis” ya da “boks,tenis” şeklinde çok sayıda kombinasyonlu değerler gelebir yani sql içerisindeki LIKE komutu ile basit bir arama yapamayız, like komutu bir string ifade içerisinde başka bir string ifadesini arar fakat bizim burada bir liste içerisinde başka bir listeyi aramamız gerekiyor bir nevi çapraz sorgulama yapmamız gerekiyor.

İşte bu işlemi yapabilmek için kendi yazdığım DoMatch fonksiyonu uye_sporlar sütununda virgül ile ayrılmış veriler arasında checkbox’larda seçilen verilerden en az bir tanesi var ise 1 hiç biri yok ise 0 değeri döndürüyor, fonksiyon iki string parametre alıyor birincisi aranan liste ikincisi içerisinde arama yapılan liste.

CREATE FUNCTION [dbo].[DoMatch](@STRING1 nvarchar(4000), @STRING2 nvarchar(4000))
RETURNS INT
AS
  BEGIN
	 DECLARE @INDEX INT
	 DECLARE @SLICE nvarchar(4000)
	 DECLARE @RTN nvarchar(2)
	 SELECT @INDEX = 1
            SET @RTN = 0
            
	        WHILE @INDEX !=0
	        BEGIN
              SELECT @INDEX = CHARINDEX(',',@STRING1)     
	            IF @INDEX !=0
	                SELECT @SLICE = RTRIM(LTRIM(LEFT(@STRING1,@INDEX - 1)))
                ELSE
	                SELECT @SLICE = RTRIM(LTRIM(@STRING1))
	            IF ',' + @STRING2 + ',' LIKE '%,' + @SLICE + ',%'  SET @RTN = 1
	            SELECT @STRING1 = RIGHT(@STRING1,LEN(@STRING1) - @INDEX)           
	            IF LEN(@STRING1) = 0 BREAK
	        END
	    RETURN @RTN
END

GO

Kuulanımı ise şöyledir;

SELECT * FROM uyeler 
WHERE dbo.DoMatch('halter,basketbol,atletizm','futbol,tenis,boks,basketbol') = 1

Bu şekilde “futbol,tenis,boks,basketbol” seçen bir üye “halter,basketbol,atletizm” filtresi için sorgumuzda gelecektir. Alternatif bir yöntem daha var; seçilen her değer için uye_sporlar sütununda like ile arama yapmak ve bunları OR operatörü ile bağlamak yani;

SELECT * FROM uyeler 
WHERE ‘,’ + uye_sporlar + ‘,’ LIKE ‘%,basketbol,%’ 
OR ‘,’ + uye_sporlar + ‘,’ LIKE ‘%,futbol,%’ 
OR ‘,’ + uye_sporlar + ‘,’ LIKE ‘%,tenis,%’

Umarım faydalı olmuştur...

Mustafa Tayyip YETİŞ
Yazılım Geliştirme Uzmanı

Yorum Yap