Baze podataka 1

Vežbe 7

Ugnježdeni upiti

U SQL-u, podupit se može jednostavno definisati kao upit unutar drugog upita. Spoljni upit se naziva glavni upit, a unutrašnji upit se naziva podupit. Drugim rečima, možemo reći da je podupit upit koji je najčešće ugrađen u WHERE klauzulu drugog SQL upita. Evo nekoliko važnih pravila za podupite:

Nezavisni ugnježdeni upiti

Kod nezavisnih ugnježdenih upita, izvršavanje upita počinje od najunutrašnjijeg upita prema spoljašnjim upitima. Izvršavanje unutrašnjeg upita je nezavisno od spoljašnjeg upita i IZVRŠAVA SE SAMO JEDNOM, ali rezultat unutrašnjeg upita se koristi pri izvršavanju spoljašnjeg upita. Različiti operatori kao što su IN, NOT IN, ANY, ALL itd. koriste se pri pisanju nezavisnih ugnježdenih upita.

SELECT *
FROM [Nastavnici]
WHERE [Snast] NOT IN
(
  SELECT [snast]
  FROM [Angazovanje]
)
Snast Imen
20 Stefanović

Upit radi to što se na početku izvrši podupit i tako dobijemo listu svih angažovanih nastavnika (njihove identifikatore). Ovo ne moramo ponavljata svaki put kada ispitujemo zasebni red, već samo jednom. Vidimo da je unutrašnji upit nezavisan od spoljašnjeg upita, jer se njegov rezultat ne menja od zavisnosti reda nad kojim se izvršava.

ALL i ANY

ALL i ANY su logički operatori u SQL-u. Oni vraćaju boolean vrednost kao rezultat.

ALL

Operator ALL se koristi za selektovanje svih n-torki iz SELECT naredbe. Takođe se koristi za poređenje vrednosti sa svakom vrednošću iz drugog skupa vrednosti ili rezultata podupita.

Operator ALL vraća TRUE ako sve vrednosti iz podupita ispunjavaju uslov. ALL mora biti prethodjen operatorima poređenja i vraća TRUE ako sve vrednosti iz podupita ispunjavaju uslov. ALL se koristi sa SELECT, WHERE i HAVING naredbama .

SELECT column_name(s)
FROM table_name
WHERE column_name comparison_operator ALL
(
  SELECT column_name
  FROM table_name
  WHERE condition(s)
)

ANY

ANY upoređuje vrednost sa svakom vrednošću iz liste ili rezultata upita i vraća TRUE ako rezultat unutrašnjeg upita sadrži barem jedan red.

ANY vraća TRUE ako bilo koja od vrednosti iz podupita ispunjava uslov.

SELECT column_name(s)
FROM table_name
WHERE column_name comparison_operator ANY
(
  SELECT column_name
  FROM table_name
  WHERE condition(s)
)

Zadaci

Korelisani ugnježdeni upiti

U realnom svetu ćemo zapravo i želeti da nam podupit daje različite rezultate na osnovu vrednosti reda nad kojim se izvršava. U tom slučaju će nam unutrušanji zavisiti od spoljnjeg glavnog upita, odnosno oni će biti korelisani. Odatle potiče termin korelisani ugnježdeni upiti.

Odradimo sada sledeci zadatak: Spisak nastavnika i predmeta (samo sifre) koji dele predmet sa jos nekim

SELECT [Snast], [Spred]
FROM [Angazovanje] a1
WHERE [Spred] IN
(
    SELECT [Spred]
    FROM [Angazovanje] a2
    WHERE a1.[Snast] != a2.[Snast] AND a1.[Spred] = a2.[Spred]
)
Snast Spred
1 2
2 2
2 11
4 10
6 10
7 15
8 15
9 11
11 24
12 24

Za razliku od nezavisnih podupita, gde se unutrasnji upit izvrsio samo jednom na samom pocetku, ovde se unutrasnji upit izvrsava ponovo za svaki red iz spoljasnjeg upita.

Odnosno, za svaki red iz tabele Angazovanje a1 ce se pozivati upit koji ce pitati da li postoji red u tabeli Angazovanje a2 da je sifra nastavnika razlicita a predmet isti.

EXISTS

Nekada želimo da izdvojimo samo one vrste za koje korelisani podupit vraća nepraznu (ili praznu) tabelu tj. ako se utvrdi da postoji (ili da ne postoji) neka vrsta koja zadovoljava uslov korelisanog podupita. Za to se može koristiti uslov EXISTS (ili NOT EXISTS, koji je zapravo samo negacija uslova EXISTS).

Operator EXISTS se koristi za testiranje postojanja bilo kog zapisa u podupitu.

Operator EXISTS vraća TRUE ako podupit vrati jedan ili više zapisa.

SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);

Odradimo primer sa nastavnicima i angazovanjima uz pomoć EXIST-a i korelisanih upita.

SELECT *
FROM [Nastavnici] n
WHERE NOT EXISTS
(
	SELECT *
	FROM [Angazovanje] a
	WHERE a.[Snast] = n.[Snast]
)
Snast Imen
20 Stefanović

Vidimo da je upit dao isti rezultat kao gore, ali je izvršen na malo drugaciji nacin.

Podupit u WHERE klauzuli sadrži poređenje nastavnikovog ID-a sa ID-em angazovanog nastavnika. To znači da će za različite redove, n.[Snast] biti različit. Zaključujemo da će unutrašnji upit morati da se izvrši za svaki red ponovo, i pritom će davata različite rezultate.

Takodje mozemo i odraditi zadatak gde 2 profesora dele predmet pomocu EXISTS naredbe.

SELECT [Snast], [Spred]
FROM [Angazovanje] a1
WHERE EXISTS
(
    SELECT *
    FROM [Angazovanje] a2
    WHERE a1.Snast != a2.Snast AND a1.Spred = a2.Spred
)

ZADACI