«« ( Date ) »» // «« ( Thread ) »» // nastava - 2003

Re: Februarski rok iz baza

by Milan Stanojevic
utorak, 04. mart 2003 - 10:34.

Wheeee!
Tacno sam uradio.
Samo sto sam ja prvo sve postavio na 0 (UPDATE Student SET Prosek=0), pa sam onda uradio setovao one koji imaju prosek.
Ajde kazi sta je resenje za 3. pod b), dekompozicija u 3NF.
Moje resenje je: (A,B,C), (C,A), (C,D), (D,E) jer je minimalna baza (AB->C, C->A, C->D, D->E).

Milan

----- Original Message -----
From: Damjan S. Vujnovic
To: NASTAVA
Sent: Monday, March 03, 2003 11:28 PM
Subject: Re: [nastava] Februarski rok iz baza


Bacio sam pogled na ovaj poslednji rok, pa samo da dam mali komentar na zadatak 2c jer je to jedan od standardnijih načina za "pecanje" (doduše pomalo ofucan, stvar je verovatno opštepoznata). Poenta je da agregatne funkcija MIN, MAX, SUM i AVG nad praznom relacijom vraćaju NULL (a ne 0) kao rezultat, pa će ono što prvo pada na pamet:

UPDATE Student
SET Student.Prosek=(SELECT AVG(I.Ocena)
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5)

studentima koji nisu položili ni jedan ispit prosek postaviti na NULL (ili još gore, ako postoji constraint da kolona nije NULL-able, ni jedan prosek se neće ažurirati jer će se transakcija Rollbackovati zbog narušavanja integriteta). Jedna ideja je da se prvo ažuriraju proseci svim studentima koji su položili barem jedan ispit:

UPDATE Student
SET Student.Prosek=(SELECT AVG(I.Ocena)
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5)
WHERE EXISTS(SELECT *
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5);

A zatim i studentima koji nisu položili ni jedan ispit:

UPDATE Student
SET Student.Prosek=0
WHERE NOT EXISTS(SELECT *
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5);

Alternativno rešenje, pretvaranjem donjih podupita u nekorelisane, upotrebom IN umesto EXISTS je:

UPDATE Student
SET Student.Prosek=(SELECT AVG(I.Ocena)
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5)
WHERE Student.SifS IN (SELECT DISTINCT I.SifS
FROM Ispit I
WHERE I.Ocena>5);

UPDATE Student
SET Student.Prosek=0
WHERE Student.SifS NOT IN (SELECT DISTINCT I.SifS
FROM Ispit I
WHERE I.Ocena>5);

Brže (a i elegantnije) rešenje je sa COALESCE (koji je uglavnom zbog toga i izmišljen):

UPDATE Student
SET Student.Prosek=COALESCE((SELECT AVG(I.Ocena)
FROM Ispit I
WHERE I.SifS=Student.SifS
AND I.Ocena>5),
0);

Pozdrav,
Damjan S. Vujnović