Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
İki sorguyu birleştirme?
#1
İki farklı Stored procedure ile yaptığım sorguyu birleştirmek istiyorum. Birşeyler yaptım ama iyi mi yaptım, kötü mü yaptım bilemedim.

AKTIF_DURUMU alanında 3 tip veri kaydettiriyorum:Aktif, Pasif,Ayrıldı. Sp'ler ile aktif ve ayrılış yapmamış(aktif+pasif toplamı) personellerin sayılarını alıyorum.

1. sp:// aktif çalışanların sayısını alıyorum.

begin
    select count(*) from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  AND AKTIF_DURUMU='Aktif'  
  INTO :AKTIF;
  suspend;
end



2. sp:// Ayrılış yapmamış personel sayılarını alıyorum.

begin
    select count(*) from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  AND AKTIF_DURUMU<>'Ayrıldı'  
  INTO :MEVCUT;
  suspend;
end


Birleştirdiğim Sp:

begin
    select (select count(*) from personel where AKTIF_DURUMU='Aktif') as AKTIF, (select count(*) from personel where AKTIF_DURUMU<>'Ayrıldı') as MEVCUT from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  INTO :AKTIF,:MEVCUT;
  suspend;
end

Bu şekildeki iç içe select sorgularında benim kullandığım şekilde count kullanılır mı? firebird sorguyu çalıştırmaya nereden başlar? Önce ana select where koşulunu mu yoksa ana select içine yazdığım selectleri mi? Önce ana select içindeki select sorguları ile -count- alanları çekiyorsa bulunan sayılar, ana selectin where şartına göre yeniden mi düzenleniyor? Ben ilk önce ana select cümlesinin where koşulunun işletildiğini düşündüğümden iki farklı sorguya göre birleştirdiğim sp'nin daha iyi olacağını düşünüyorum. Yaptığım şey mantıklı mı, hız ve performans açısından bir faydası olur mu?
Cevapla
#2
Sizin durumunuzda hız ve performans için tek sorgu yada 2 sorgu pekte önemli değil bence, zira bir programa kaç tane personel tanıtabilirsiniz ki ? binlerce, onbinlerce olmayacak sonuçta. Ama, kod kısa, derli toplu olsun derseniz elbetteki yararı olacaktır.

Bunun yanında ben olsam AKTIF_DURUMU alanını smallint gibi bişi yapardım (bir tek bu tablo için düşünmeyin), 0:aktif 1:pasif 2:ayrıldı vs.vs. gibi. Bunu on binlerce kayıt girilen fatura tablosuna tablosunda kullandığınızı düşünün, türü varchar(10) deyip 10 byte kullanmak var, türü smallint deyip 2 byte kullanmak var, 10k kayıtta her bir byte size 10k ek yük getirir şeklinde düşünün, bunun yanında ağdan bağlanan kullanıcılar içinde türü=0 demek var, türü=alış faturası demek var, buda size her bir sorguda fazladan ağ trafiğine ek yük bindirmek olacaktır.
WWW
Cevapla
#3
(10-05-2018, Saat: 00:21)canbir Adlı Kullanıcıdan Alıntı: İki farklı Stored procedure ile yaptığım sorguyu birleştirmek istiyorum. Birşeyler yaptım ama iyi mi yaptım, faydasız veya kötü birşey mi yaptım bilemedim. Yaptığım şey mantıklı mı, hız ve performans açısından bir faydası olur mu?

AKTIF_DURUMU alanında 3 tip veri kaydettiriyorum:Aktif, Pasif,Ayrıldı. Sp'ler ile aktif ve ayrılış yapmamış(aktif+pasif toplamı) personellerin sayılarını alıyorum.

1. sp:// aktif çalışanların sayısını alıyorum.
begin
    select count(*) from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  AND AKTIF_DURUMU='Aktif'  
  INTO :AKTIF;
  suspend;
end


2. sp:// Ayrılış yapmamış personel sayılarını alıyorum.
begin
    select count(*) from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  AND AKTIF_DURUMU<>'Ayrıldı'  
  INTO :MEVCUT;
  suspend;
end

Birleştirdiğim Sp:
begin
    select (select count(*) from personel where AKTIF_DURUMU='Aktif') as AKTIF, (select count(*) from personel where AKTIF_DURUMU<>'Ayrıldı') as MEVCUT from personel
  where UNVANI=:UNVANI
  AND GOREV_YERI=:GOREV_YERI
  INTO :AKTIF,:MEVCUT;
  suspend;
end

Bir count sorgusu tek satır döndürmesi gerekirken sizin sorgunuz potansiyel olarak onlarca satır döndürebilir ve performans olarak da pek iyi değil açıkçası. Aşağıdaki kodu bir inceleyin:

begin
   select 
      count(case when aktif_durumu='Aktif' then id end) as aktif,
      count(case when aktif_durumu<>'Ayrıldı' then id end) as mevcut
   from personel
   where unvani=:unvani and gorev_yeri=:gorev_yeri
   into :aktif,:mevcut;
   suspend;
end


Cevapla
#4
(10-05-2018, Saat: 09:26)edo Adlı Kullanıcıdan Alıntı: Bir count sorgusu tek satır döndürmesi gerekirken sizin sorgunuz potansiyel olarak onlarca satır döndürebilir ve performans olarak da pek iyi değil açıkçası. Aşağıdaki kodu bir inceleyin:

begin
   select 
      count(case when aktif_durumu='Aktif' then id end) as aktif,
      count(case when aktif_durumu<>'Ayrıldı' then id end) as mevcut
   from personel
   where unvani=:unvani and gorev_yeri=:gorev_yeri
   into :aktif,:mevcut;
   suspend;
end


Yanlış yorumlamış olabilirim ama, önerdiğiniz kodun sonuç olarak şöyle uygulanacağını düşünüyorum.

begin
  select 
     count(ID) as aktif,
     count(ID) as mevcut
  from personel
  where unvani=:unvani and gorev_yeri=:gorev_yeri
  into :aktif,:mevcut;
  suspend;
end

Bu durumda da hem aktif hem mevcut için aynı sayıyı vermez mi?
Cevapla
#5
(10-05-2018, Saat: 09:21)esistem Adlı Kullanıcıdan Alıntı: Sizin durumunuzda hız ve performans için tek sorgu yada 2 sorgu pekte önemli değil bence, zira bir programa kaç tane personel tanıtabilirsiniz ki ? binlerce, onbinlerce olmayacak sonuçta. Ama, kod kısa, derli toplu olsun derseniz elbetteki yararı olacaktır.

Bunun yanında ben olsam AKTIF_DURUMU alanını smallint gibi bişi yapardım (bir tek bu tablo için düşünmeyin), 0:aktif 1:pasif 2:ayrıldı vs.vs. gibi. Bunu on binlerce kayıt girilen fatura tablosuna tablosunda kullandığınızı düşünün, türü varchar(10) deyip 10 byte kullanmak var, türü smallint deyip 2 byte kullanmak var, 10k kayıtta her bir byte size 10k ek yük getirir şeklinde düşünün, bunun yanında ağdan bağlanan kullanıcılar içinde türü=0 demek var, türü=alış faturası demek var, buda size her bir sorguda fazladan ağ trafiğine ek yük bindirmek olacaktır.
Aslında bu kodu çok yoğun şekilde kullanacağım, ayrıca personel sayısı, görev yeri ve unvan sayısı da fazla miktarda. Yazdığım sorgunun ne getirip götüreceğinden emin olamamamın asıl nedeni, select sorgusunun işleyisiyle alakalı. Eğer ilk önce where bölümü işletiliyorsa olumlu bir etkisi olur, fakat ilk önce select ile çekilen alanlar çekiliyorsa, orada iki adet ek select cümlesi olduğundan o zaman bir fark olmaz. Bu durumda bile sizin de dediğiniz gibi daha derli toplu olması açısından tek sp olarak kullanmak daha mantıklı.

Diğer konu için de aslında ben de en az yer işgal edecek şekilde alanlarımı tanımlamaya gayret ediyorum. Kullanıcıya dbcombobox ile seçim yaptırmayı planlıyordum. Sizin uyarınız üzerine veri tipini değiştirip kullanıcıya da dbradiogroup ile seçim yaptırsam nasıl olur diye bir bakayım.


Yorum yapan arkadaşlara teşekkür ediyorum. (+ rep)
Cevapla
#6
(10-05-2018, Saat: 12:32)canbir Adlı Kullanıcıdan Alıntı:
(10-05-2018, Saat: 09:26)edo Adlı Kullanıcıdan Alıntı: Bir count sorgusu tek satır döndürmesi gerekirken sizin sorgunuz potansiyel olarak onlarca satır döndürebilir ve performans olarak da pek iyi değil açıkçası. Aşağıdaki kodu bir inceleyin:

begin
   select 
      count(case when aktif_durumu='Aktif' then id end) as aktif,
      count(case when aktif_durumu<>'Ayrıldı' then id end) as mevcut
   from personel
   where unvani=:unvani and gorev_yeri=:gorev_yeri
   into :aktif,:mevcut;
   suspend;
end


Yanlış yorumlamış olabilirim ama, önerdiğiniz kodun sonuç olarak şöyle uygulanacağını düşünüyorum.

begin
  select 
     count(ID) as aktif,
     count(ID) as mevcut
  from personel
  where unvani=:unvani and gorev_yeri=:gorev_yeri
  into :aktif,:mevcut;
  suspend;
end

Bu durumda da hem aktif hem mevcut için aynı sayıyı vermez mi?

Sizin kodunuz iki kolonda da aynı veriyi döndürürken, benim size söylediğim yöntem ayrı ayrı aktif ve mevcut sayısı verir. Uzak yakın alakası yok yani  Wink
Cevapla
#7
önce where ile ürün tablo elde edilir sonra bu ürün tablodan select içindeki select satırları tetiklenir. Gönlünüz rahat olsun.

SQL performans deyince akla ilk gelen index'lerdir. Bunları ihmal etmeyin. 

where kısmına tarih aralığı gibi sınırlayıcı öncü satırlar çabuk elemeye yardımcı olur.

where kısmında hesaplama yaptırmaktan kaçının, yani where a_field * b_field >100 gibi hesaplardan bahis.

select ile gereksiz field çekmeyin, sadeleştirin. ortak select procedure yapınız varsa bu ortak procedure / function için parametreler ile donatıp join table ve/veya select field sayısını minimuma indirgemeye çalışın. (sql params gibi yanlış algılamayın) 

Bunlara dikkat ederseniz sql performansı artacaktır.
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#8
(10-05-2018, Saat: 14:01)edo Adlı Kullanıcıdan Alıntı:
(10-05-2018, Saat: 12:32)canbir Adlı Kullanıcıdan Alıntı: Yanlış yorumlamış olabilirim ama, önerdiğiniz kodun sonuç olarak şöyle uygulanacağını düşünüyorum.

begin
  select 
     count(ID) as aktif,
     count(ID) as mevcut
  from personel
  where unvani=:unvani and gorev_yeri=:gorev_yeri
  into :aktif,:mevcut;
  suspend;
end

Bu durumda da hem aktif hem mevcut için aynı sayıyı vermez mi?

Sizin kodunuz iki kolonda da aynı veriyi döndürürken, benim size söylediğim yöntem ayrı ayrı aktif ve mevcut sayısı verir. Uzak yakın alakası yok yani  Wink

Doğrusu hiç aklıma yatmamıştı ama ikinci yazınız üzerine veritabanına kayıt oluşturup denedim. Önerdiğiniz kod gerçekten de doğru sonuç veriyor. Ben üstte yazdığım gibi olacağını düşünmüştüm ama demek ki yanlış düşünmüşüm. Yardımınız için çok teşekkür ederim.
Cevapla
#9
(10-05-2018, Saat: 14:16)mrmarman Adlı Kullanıcıdan Alıntı: önce where ile ürün tablo elde edilir sonra bu ürün tablodan select içindeki select satırları tetiklenir. Gönlünüz rahat olsun.

SQL performans deyince akla ilk gelen index'lerdir. Bunları ihmal etmeyin. 

where kısmına tarih aralığı gibi sınırlayıcı öncü satırlar çabuk elemeye yardımcı olur.

where kısmında hesaplama yaptırmaktan kaçının, yani where a_field * b_field >100 gibi hesaplardan bahis.

select ile gereksiz field çekmeyin, sadeleştirin. ortak select procedure yapınız varsa bu ortak procedure / function için parametreler ile donatıp join table ve/veya select field sayısını minimuma indirgemeye çalışın. (sql params gibi yanlış algılamayın) 

Bunlara dikkat ederseniz sql performansı artacaktır.

Bilgilendirme için teşekkür ederim. İlk mesajımdaki merak ettiğim konular artık kafamı kurcalamayacak.
Cevapla
#10
(10-05-2018, Saat: 15:41)canbir Adlı Kullanıcıdan Alıntı:
(10-05-2018, Saat: 14:16)mrmarman Adlı Kullanıcıdan Alıntı: önce where ile ürün tablo elde edilir sonra bu ürün tablodan select içindeki select satırları tetiklenir. Gönlünüz rahat olsun.

SQL performans deyince akla ilk gelen index'lerdir. Bunları ihmal etmeyin. 

where kısmına tarih aralığı gibi sınırlayıcı öncü satırlar çabuk elemeye yardımcı olur.

where kısmında hesaplama yaptırmaktan kaçının, yani where a_field * b_field >100 gibi hesaplardan bahis.

select ile gereksiz field çekmeyin, sadeleştirin. ortak select procedure yapınız varsa bu ortak procedure / function için parametreler ile donatıp join table ve/veya select field sayısını minimuma indirgemeye çalışın. (sql params gibi yanlış algılamayın) 

Bunlara dikkat ederseniz sql performansı artacaktır.

Bilgilendirme için teşekkür ederim. İlk mesajımdaki merak ettiğim konular artık kafamı kurcalamayacak.

Aman hocam, bunlar en önemli konular. Bunların kafanızı bolca kurcalaması lazım. Sorgu optimizasyonu, doğru/yanlış index kullanımı vs. bunları bol bol araştırın. Yoksa veritabanını en güçlü sunucuya koysanız yine kaynakları tüketirsiniz  Big Grin
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Satır Birleştirme sunbeki 9 1.502 13-10-2023, Saat: 15:30
Son Yorum: sunbeki
  Tablo birleştirme muratmert 7 1.665 13-04-2023, Saat: 09:24
Son Yorum: mrmarman
  Sorguyu Hızlandırma sunbeki 3 1.157 09-04-2022, Saat: 22:50
Son Yorum: sunbeki
  Tabloda Alan Birleştirme sunbeki 6 1.735 06-04-2022, Saat: 20:40
Son Yorum: MugenPower
  FB Birden Fazla sorguyu çalıştırma mcuyan 6 4.240 10-01-2019, Saat: 23:47
Son Yorum: mcuyan



Konuyu Okuyanlar: 2 Ziyaretçi