PL/SQL WITH KULLANIMI

WITH komutu ile, alt sorgulara isim atamak ve bu alt sorguyu diğer alt sorgularda atanan isim ile kullanmak mümkündür. Kendisini tanımladığınız alt sorgu dışındaki bütün alt sorgularda kullanılabilmektedir.
WITH komutu, aynı alt sorguya bir kaç yerde baş vurmak gerektiği durumlarda, kod tekrarı yapmadan işlem yapabilmeyi sağlamaktadır. Bu şekilde sorgular hem daha okunur olmakta, hem de optimize çalışmaktadır.

Genel Kullanımı

with sorgu_1 as (select * from table1 where ...),
     sorgu_2 as (select * from table2 where ...),
     ...
     select * from sorgu_1, sorgu_2,... where ....

Örneğimiz şu şekilde olacaktır;
Özel bir şirkette performans ve mesai prim ödemesi yapılacaktır. Bir personelin 1000 TL’lik performans primini alabilmesi için performans puanının 80 ve üzerinde olması ve çalıştığı birimin de performans ortalaması 80 ve üzerinde olması gerekmektedir. Personelin 500 TL’lik mesai primini alabilmesi için 30 saat ve üzerinde mesai yapmış olması ve birim ortalama mesai saatinin de 30 saat ve üzerinde olması gerekmektedir. Her iki primi hak eden personel sadece performans primini yani 1000 TL alabilecektir. Bu şartlara göre prim alacak personelleri ve alacağı prim tutarını getiren sql sorgumuzu yazalım.

Kullanacağımız tabloları oluşturup örnek kayıtlar ekleyelim.

create table BIRIM
(
  birim_id  NUMBER,
  birim_adi VARCHAR2(50)
)
;

insert into BIRIM (birim_id, birim_adi)
values (1, 'Muhasebe');
insert into BIRIM (birim_id, birim_adi)
values (2, 'İnsan Kaynakları');
insert into BIRIM (birim_id, birim_adi)
values (3, 'Ar-ge');
create table PERSONEL
(
  personel_id NUMBER,
  adi         VARCHAR2(50),
  soyadi      VARCHAR2(50),
  birim_id    NUMBER
)
;

insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (1, 'Koray', 'Uzun', 3);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (2, 'Ayşe', 'Özer', 1);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (3, 'Metin', 'Yurttaş', 2);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (4, 'Eda', 'Kürkçü', 3);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (5, 'Sedef', 'Çakır', 3);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (6, 'Osman', 'Aydın', 1);
insert into PERSONEL (personel_id, adi, soyadi, birim_id)
values (7, 'Hakan', 'Genç', 2);
create table PERFORMANS
(
  personel_id NUMBER,
  puan        NUMBER
)
;

insert into PERFORMANS (personel_id, puan)
values (1, 80);
insert into PERFORMANS (personel_id, puan)
values (2, 60);
insert into PERFORMANS (personel_id, puan)
values (3, 80);
insert into PERFORMANS (personel_id, puan)
values (4, 90);
insert into PERFORMANS (personel_id, puan)
values (5, 80);
insert into PERFORMANS (personel_id, puan)
values (6, 90);
insert into PERFORMANS (personel_id, puan)
values (7, 95);
create table MESAI
(
  personel_id NUMBER,
  mesai_saati NUMBER
)
;

insert into MESAI (personel_id, mesai_saati)
values (4, 0);
insert into MESAI (personel_id, mesai_saati)
values (1, 40);
insert into MESAI (personel_id, mesai_saati)
values (2, 20);
insert into MESAI (personel_id, mesai_saati)
values (3, 5);
insert into MESAI (personel_id, mesai_saati)
values (5, 45);
insert into MESAI (personel_id, mesai_saati)
values (6, 50);
insert into MESAI (personel_id, mesai_saati)
values (7, 60);

WITH işlevini kullanarak istenen kayıtları bulan sql;

with 
 birim_ortalama as  -- Bütün birimlerin ortalama performans ve mesaisi bulunuyor
  (select b.birim_id,
         b.birim_adi,
         sum(puan) / count(*) performans_ort,
         sum(mesai_saati) / count(*) mesai_ortalama
    from birim b, personel p, performans r, mesai m
   where b.birim_id = p.birim_id
     and p.personel_id = r.personel_id
     and p.personel_id = m.personel_id
   group by b.birim_id, b.birim_adi),

performans_prim as  -- Prim alacak personeller bulunuyor
 (select '1000 TL' as prim_tutar, p.personel_id, p.adi, p.soyadi, p.birim_id
    from personel p, performans r
   where p.personel_id = r.personel_id
     and r.puan >= 80
     -- Personelin birim ortalamasının da >=80 kontrolü
     and exists (select *
            from birim_ortalama bo
           where bo.birim_id = p.birim_id
             and bo.performans_ort >= 80)),

mesai_prim as  -- -- Prim alacak personeller bulunuyor
 (select '500 TL' as prim_tutar, p.personel_id, p.adi, p.soyadi, p.birim_id
    from personel p, mesai m
   where p.personel_id = m.personel_id
     and m.mesai_saati >= 30
     -- Personelin birim ortalamasının da >=30 kontrolü
     and exists (select *
            from birim_ortalama bo
           where bo.birim_id = p.birim_id
             and bo.mesai_ortalama >= 30))
select *
  from performans_prim --performans_prim olarak adlandırdığımız sorguyu listele
union
select *
  from mesai_prim mp   --mesai_prim olarak adlandırdığımız sorguyu listele
 where not exists (select 1  -- Performans primi alan personel mesai almasın
    from performans_prim pp
   where pp.personel_id = mp.personel_id);
PRIM_TUTAR PERSONEL_ID ADI      SOYADI   BIRIM_ID
1000 TL	    1	       Koray	Uzun	  3
1000 TL	    3	       Metin	Yurttaş	  2
1000 TL	    4	       Eda	Kürkçü	  3
1000 TL	    5	       Sedef	Çakır	  3
1000 TL	    7	       Hakan	Genç	  2
500 TL	    6	       Osman	Aydın	  1