SQL – korišćenje podupita u rešavanju problema

 

 

 

U SQL-u rezultat jednog upita može biti dinamički zamenjen u WHERE klauzuli drugog upita. Ova činjenica može biti iskorištena za rešavanje sledećeg problema:

 

1. Prikazati ime, posao i platu onih radnika, koji imaju platu veću od Milana.

 

Ideja za rešenje ovog problema prikazana je na sledećoj slici:

 

 

 

U ovom scenariu, podupit (unutrašnji upit) se izvršava pre glavnog upita (spoljnog upita), a onda se rezultat podupita koristi u glavnom upitu. Rešenje se daje u nastavku.

 

SELECT IME, POSAO, PLATA

FROM RADNIK

WHERE PLATA > (SELECT PLATA FROM RADNIK

WHERE IME = 'Milan');

 

Tipovi podupita

 

Prema skupu vrednosti koji vraćaju, podupiti se mogu podeliti na:

 

  • Single-row podupiti: Upiti koji vraćaju samo jednu vrednost iz unutrašnje SELECT naredbe

 

  • Multiple-row podupiti: Upiti koji vraćaju više od jedne vrednost iz unutrašnje SELECT naredbe

 

Treba naglasiti da postoje, takođe, multiple-column podupiti, koji vraćaju više od jedne kolone iz unutrašnje SELECT naredbe.

 

Tipovi podupita, u napred navedenom smislu, ilustovani su na sledećoj slici.

 

 

 

Single-Row podupiti

 

Single-Row podupiti vraćaju samo jednu vrednost, i u njihovom kontekstu mogu se koristiti samo single-row (skalarni) operatori. Single-row (skalarni) operatori su prikazani na sledećoj slici.

 

 

 

Ponekad, da bi smo osigurali da podupit vrati samo jednu vrednost možemo koristiti sumarnu (agregatnu) funkciju.

 

2. Prikazati ime, posao i platu onih radnika koji imaju najmanju platu u firmi.

 

SELECT ime, posao, plata

FROM radnik

WHERE plata = (SELECT MIN(plata)

FROM radnik);

 

Podupiti se mogu izvršavati i u HAVING klauzuli.

 

3. Prikazati sifru odeljenja i minimalnu platu u njemu, i to za ona odeljenja u kojima je minimalna plata veća nego u odeljenju 20.

 

SELECT odeljenje#, MIN(plata) as min_plata

FROM radnik

GROUP BY odeljenje#

HAVING MIN(plata) > (SELECT MIN(plata)

FROM radnik

WHERE odeljenje# = 20);

 

Multiple-row podupiti

 

Na sledećojslici je ilustrovana nekorektna upotreba skalarnog operatora u podupitu. U kontekstu Multiple-row podupita moraju se koristiti multiple-row upoređujući operator.

 

 

 

Multiple-row upoređujući operatorisu prikazani na sledećoj slici.

 

 

 

4. Prikazati ime, posao i platu radnika u odeljenju 20 koji imaju isti posao kao radnici odeljenja projektovanje.

 

SELECT IME, POSAO, PLATA

FROM RADNIK

WHERE ODELJENJE# = 20

AND POSAO IN

(SELECT POSAO FROM RADNIK

WHERE ODELJENJE# IN

(SELECT ODELJENJE# FROM ODELJENJE

WHERE NAZIV = 'PROJEKTOVANJE'));

Operator IN se može negirati, tj. koristiti NOT IN.

 

5. Prikazati sifru radnika, sifru rukovodioca i ime radnika koji nisu rukovodioci

Prvo rešenje koje se nameće za ovaj primer je:

 

SELECT r.sradnik, r.srukov, r.ime

from radnik r

where r.sradnik NOT IN
(SELECT rukovodioc.srukov FROM Radnik rukovodioc)

Međutim, ovaj upit ne vraća nijedan red, što nas na prvi mah iznenađuje, jer znamo da postoje radnici koji nisu rukovodioci. Odgovor leži u semantici operatora NOT IN. Naime, on je ekvivalentan operatoru !=ALL. Izvor problema je postojanje vrednosti NULL u rezultatu podupita (postoji radnik koji nema rukovodioca). Eliminisanjem NULL vrednosti iz podupita, dobijamo korektno rešenje:

 

SELECT r.sradnik, r.srukov, r.ime

from radnik r

where r.sradnik NOT IN (SELECT rukovodioc.srukov

FROM Radnik rukovodioc

WHERE rukovodioc.srukov IS NOT NULL) ;

 

Situacija u prethodnom upitu je česta u praksi, i na grešku nisu imuni ni iskusni korisnici SQL-a. Dodatni problem je što manifestacija lošeg rešenja može nastati posle puštanja nekog sistema u operativnu upotrebu, kada se ova vrsta (tj. uzrok problema) greške teško otkriva.

 

 

Dodaj komentar Sviđa mi se - (0) Ne sviđa mi se - (0)    

  • SQL – korišćenje podupita u rešavanju problema 1
  • SQL – korišćenje podupita u rešavanju problema 2