Domáca úloha --- Riešenia. Domáca úloha - Riešenia.

Databáza je o amerických filmoch:

        Filmy(názov, režisér, rok)
        Obsadenia(názov, herec, plat)
        Recenzie(názov, kritik, hodnotenie)

Atribúty sú reťazce okrem atribútov rok, plat, a hodnotenie, ktoré sú celé čísla. Kvôli stručnosti a prehľadnosti používajte skrátenú schému:

        F(n, r, d),
        O(n, h, p),
        R(n, k, v).

Dotazy napíšte tak, aby výsledky neobsahovali duplikáty riadkov, ale nepoužívajte DISTINCT tam, kde je to zbytočné.

Napíšte nasledujúce dotazy:

(a) Nájdite režisérov, ktorí aj hrali (pomocou poddotazu vo WHERE).

        SELECT DISTINCT r
        FROM F
        WHERE r IN (SELECT h FROM O);

Kalkul: $(u,x,y,z) F(u,r,x) ŮO(y,h,z)

Algebra: Pr F ÇPh O

(b) Nájdite hercov, korí nikdy nerežírovali (bez použitia poddotazu vo WHERE).

        (SELECT h FROM O)
        EXCEPT
        (SELECT r FROM F);

Úlohu možno splniť aj keď používaná implementácia SQL nepodporuje rozdiel.

        SELECT h
        FROM O LEFT OUTER JOIN F ON h = r
        WHERE r IS NULL;

Kalkul: $(u,x,y,z) O(y,h,z) ŮŘF(u,r,x)

Algebra: Ph O - Pr F

(c) Nájdite názvy všetkých filmov zo 60-tých rokov, kde hrali spolu Dustin Hoffman a Anne Bancroft.

        SELECT F.n
        FROM F, O O1, O O2
        WHERE F.n = O1.n
              AND F.n = O2.n
              AND d >= 1960 AND d < 1970 /* d BETWEEN 1960 AND 1969 */
              AND O1.h = "Dustin Hoffman"
              AND O2.h = "Anne Bancroft";

Kalkul: $(r,d,p1, p2) F(n,r,d) ŮO(n, "DH", p1) Ů O(n, ÄB", p2) Ůd ł 1960 Ůd < 1970

Algebra: Pn sd ł 1960 Ůd < 1970 Ůh1 = "DH" Ůh2 = ÄB" (F(n,r,d) \bowtieO(n, h1, p1) \bowtieO(n, h2, p2)) (d) Bez použitia rozdielu (EXCEPT, -), nájdite všetkých hercov, ktorí hrali vo všetkých filmoch režírovaných Kurosawom. (Herec hral vo všetkých filmoch režírovaných Kurosawom, ak neexistuje film režírovaný Kurosawom, ktorý sa nenachádza medzi filmami v ktorých daný herec hral.)

        SELECT DISTINCT O1.h
        FROM O O1
        WHERE  NOT EXISTS
               (SELECT *
                FROM   F
                WHERE  r = "Kurosawa"
                      AND  F.n NOT IN
                                     (SELECT O2.n
                                      FROM O O2
                                      WHERE  O2.h = O1.h));

Použitie počítacieho argumentu - counting argument (Herec hral vo všetkých filmoch režírovaných "Kurosawom", ak hral v toľkých filmoch režírovaných Kurosawom, koľko ich Kurosawa režíroval.) je možné, má svoje uskalia a sťaží aj logické a algebraické vyjadrenie dotazu.

        SELECT h
        FROM F, O
        WHERE  F.r = "Kurosawa" AND O.n = F.n
        GROUP BY h
        HAVING COUNT(n) = (SELECT COUNT(*) FROM F WHERE F.r = "Kurosawa");
             /* Čo ak dvojroľa v Kurosawovom filme ?*/

Kalkul: "(n, d)F(n, "Ku", d) Ţ$(p)O(n, h, p)

Algebra: Ph (O(n,h,p) - Ph ( ( Pn(sr = "Ku"F(n,r,d)) ×PhO(n,h, p))- Pn,h O(n,h,p))

(e) Nájdite názvy všetký filmov, ktoré recenzovali aspoň dvaja kritici (s použitím agregačnej funkcie).

        SELECT n
        FROM R
        GROUP BY n
        HAVING COUNT(*) > 1;

(f) To isté ako (e), ale s použitím poddotazu namiesto agregačnej funkcie.

        SELECT DISTINCT n
        FROM R R1
        WHERE EXISTS /* R1.n IN */ (SELECT R2.n
                                    FROM R R2
                                    WHERE R1.k <> R2.k);

(g) To isté ako (e), ale bez poddotazu aj bez agregačnej funkcie.

        SELECT DISTINCT R1.n
        FROM R R1, R R2
        WHERE R1.n = R2.n
              AND R1.k <> R2.k;

Kalkul: $(k1, k2, v1, v2) R(n, k1, v1) ŮR(n, k2, v2) Ůk1 ą k2

Algebra: Pn sk1 ą k2 R(n, k1, v1) \bowtieR(n, k2, v2)

(h) Pomocou agregačnej funkcie zistite názvy všetkých filmov, ktoré majú práve jednu recenziu.

        SELECT n
        FROM R
        GROUP BY n
        HAVING COUNT(*) = 1;

(i) To isté ako (h), ale nepoužite agregačné funkcie.

        SELECT n
        FROM R R1
        WHERE NOT EXISTS (SELECT *
                          FROM R R2
                          WHERE R1.k <> R2.k);

Iná alternativa

        SELECT n
        FROM R R1
        WHERE R1.n NOT IN (SELECT R2.n
                           FROM R R2
                           WHERE R1.k <> R2.k);

Kalkul: "(k1,v1,k2,v2) R(n,k1,v1) Ů(R(n,k2,v2) Ţk1 = k2

Algebra: Pn R - Pn sk1 ą k2(R(n,k1,v1) \bowtieR(n,k2,v2))

(j) Pre všetkých kritikov vypočítajte priemerné hodnotenie, ktoré udelili. Vypíšte len tých, ktorých priemerné hodnotenie je väčšie ako 1 a usporiadajte ich zostupne podľa hodnotenia.

        SELECT k, AVG(v)
        FROM R
        GROUP BY k
        HAVING AVG(v) >= 1;
(k) Definujeme hodnotu filmu ako priemerné hodnotenie udelené mu kritikmi. Vypíšte: názov, hodnotenie, a rok pre najvyššie hodnotené filmy každého roku. Filmy majú byť usporiadane podľa hodnotenia zostupne. Pri rovnakom hodntení majú byť novšie filmy uvedné skôr.

        SELECT   n, d, AVG(v),
        FROM     F, R
        WHERE    F.n = R.n
        GROUP BY n, d
        ORDER BY AVG(v) DESC, d DESC;

Niekto, mohol pochopiť, že treba vytlačiť iba názvy filmov s maximálnym priemerom za každý rok.

        SELECT   R1.n, d, AVG(R1.v)
        FROM     F F1, R R1
        WHERE    F1.n = R1.n
        GROUP BY R1.n, d
        HAVING AVG(R1.v) >= ALL (SELECT AVG(R2.v)
                                 FROM R R2, F F2
                                 WHERE R2.n = F2.n AND F2.d = F1.d
                                 GROUP BY R2.n , F2.d )
       ORDER BY d DESC;

(l) Definujte hodnotenie režiséra ako priemerné hodnotenie jeho filmov. Nájdite mená hodnotenia všetkých režisérov, ktorí režírovali filmy s Al Pacinom.

        SELECT   r, AVG(fv)
        FROM     F, (SELECT n, AVG(v) AS fv FROM R GROUP BY n) FA
        WHERE    F.n = FA.n
        GROUP BY r
        HAVING   r IN
                      (SELECT r
                       FROM   F, O
                       WHERE  F.n = O.n
                              AND h = "Al Pacino");
Nie každý SQL podporuje poddotaz za FROM v takom prípade je potrebné tento poddotaz naharadiť príkazom:
        CREATE VIEW FA AS (SELECT n, AVG(v) AS fv FROM R GROUP BY n);
        /* Vyžaduje právo modifikovať schéma a zapisovať do databázy. */
        SELECT   r, AVG(fv)
        FROM     F, FA
        WHERE    F.n = FA.n
        GROUP BY r
        HAVING   r IN
                      (SELECT r
                       FROM   F, O
                       WHERE  F.n = O.n
                              AND h = "Al Pacino");
        DROP VIEW FA; /* Inak by view zostalo v databáze. */

Poddotaz vo FROM vytvára dočasný pohľad v pracovnom priestora nevyžaduje právo zápisu do databázy.

(m) Je uvedený dotaz spráne riešenie (l)? Zdôvodnite svoju odpoveď.

        SELECT r, AVG(v)
        FROM Filmy F, Recenzie R
        WHERE
              F.n IN (SELECT n FROM Obsadenie WHERE h = "Al Pacino")
              AND F.n = R.n;

Nie. Počíta priemer filmov a nie režisérov (priemer priemerov).Navyše obsahuje aj syntaktickú chybu. Chýba GROUP BY.

(n) Pre každý rok nájdite herca, ktorý v danom roku najviac zarobil (súčet platov za všetky filmy v ktorých učinkoval).

        SELECT F1.d, O1.h, SUM(O1.p)
        FROM F F1, O O1
        WHERE F1.n = O1.n
        GROUP BY F1.d, O1.h
        HAVING SUM(P) >= ALL (SELECT SUM(O2.p)
                              FROM F F2, O O2
                              WHERE F2.n = O2.n AND F2.d =  F1.d
                              GROUP BY h);

Ani vložené GROUP BY nemusí podporovať každá implemetácia SQL. Na druhej strane v ORACLE možno namiesto ALL použiť aj MAX(SUM(O2.p)).


File translated from TEX by TTH, version 2.00.
On 15 Nov 1999, 20:00.