ÖVNING 14 SAL(SalsId, Max_antalpersoner) AVSTÅND(Sal1, Sal2, Längd) DANSARE(Namn, Skostorlek, Längd) BALETT(Namn, Upphovsman) ROLL(RollNamn, BalettNamn) UPPSÄTTNING(BalettNamn, Från, Till) ROLLINNEHAV(Dansare, Roll, Balett, Från, Till) (Primärnycklar är angivna med fetstil.) AVSTÅND.Sal 1 << Sal.SalsId AVSTÅND.Sal2 << Sal.SalsId ROLL.Ballettnamn << BALETT.Namn UPPSÄTTNING.Balettnamn << BALETT.Namn ROLLINNEHAV.Dansare << DANSARE.Namn ROLLINNEHAV.(Roll, Balett) << ROLL.(RollNamn, BalettNamn) ROLLINNEHAV.(Ballett, Från, Till) << UPPSÄTTNING(BalettNamn,F rån, Till). Formulera följande frågor i a) SQL b) Relationsalgebra 1) Vilka dansare är över två meter långa och har dansat i Svansjön? PI Namn (SIGMA Längd > 2.0 AND Balett= Svansjön (ROLLINNEHAV) JOIN ROLLINNEHAV.Dansare=DANSARE.Namn DANSARE) SELECT Namn FROM DANSARE, ROLLINNEHAV WHERE DANSARE.Namn=ROLLINNEHAV.Dansare AND Längd > 2.0 AND Balett = Svansjön
2) Vlka dansare har dansat i en balett skriven av Pucini och vilken är deras skostorlek? Pucini-baletter := PI Namn (SIGMA Upphovsman = Pucini (BALETT)) Pucini-dansare := PI Dansare ( Pucini-baletter JOIN Balett = Namn ROLLINNEHAV) PI Namn, Skostorlek ( ROLLINNEHAV JOIN ROLLINNEHAV.Dansare=DANSARE.Namn DANSARE) SELECT Namn FROM DANSARE, ROLLINNEHAV, BALETT WHERE BALETT.Upphovsman= Pucini AND BALETT.Namn=ROLLINNEHAV.Balett AND DANSARE.Namn=ROLLINNEHAV.Dansare 3) Vad är genomsnittlig längd för de dansare som dansat i baletten Svansjön eller i baletten Törnrosa? F AVG(Längd) (SIGMA Baltett= Törnrosa OR Balett= Svansjön (ROLLINNEHAV) JOIN DANSARE) SELECT AVG(Längd) AS Dansarmedellängd FROM DANSARE, ROLLINNEHAV WHERE DANSARE.Namn=ROLLINNEHAV.Dansare AND (Balett = Törnrosa OR Balett = Svansjön ) 4) Vilka upphovsmän har skrivit mer än en balett? ROLLINNEHAV.Dansare=DANSARE.Namn Kandidater(Mästare, Antal_baletter) := Upphovsman F COUNT(Namn) (BALETT) Resultat(Namn) := PI Mästare (SIGMA Antal_baletter > 1 (Kandidater)) SELECT Upphovsman FROM BALETT GROUP BY Upphovsman HAVING COUNT(Namn) > 1
5) Vilka dansare har inte dansat i baletten Svansjön men i baletten Törnrosa? Rosorna PI (Dansare) (SIGMA Balett= Törnrosa (ROLLINNEHAV)) Svanorna PI (Dansare) (SIGMA Balett= Svansjön (ROLLINNEHAV)) Svar Rosorna - Svanorna CREATE VIEW Rosorna AS (SELECT Dansare FROM ROLLINNEHAV WHERE Balett = Törnrosa ) CREATE VIEW Svanorna AS (SELECT Dansare FROM ROLLINNEHAV WHERE Balett = Svansjön ) SELECT * FROM Rosorna EXCEPT SELECT * FROM Svanorna 6) För vilka baletter finns det inga uppsättningar? Uppsatta_baletter PI (BalettNamn) (UPPSÄTTNING) Baletter PI (Namn) (BALETT) Svar Baletter - Uppsatta_baletter CREATE VIEW Uppsatta_baletter AS (SELECT BalettNamn FROM UPPSÄTTNING) CREATE VIEW Baletter AS (SELECT Namn As BalettNamn FROM BALETT) SELECT * FROM Baletter EXCEPT SELECT * FROM Uppsatta_baletter
7) Vilka dansare har dansat alla rollerna i Svansjön? Svanroller(RollNamn) PI (RollNamn) ( SIGMA BalettNamn= Svansjön (ROLL)) Dansat(Namn, RollNamn) PI (Dansare, Roll) ( SIGMA Balett= Svansjön (ROLLINNEHAV)) (Notera att man behöver kontrollera att det verkligen är svansjö-roller i sista satsen, pga det kan finnas roller med samma namn i olika baletter!) Svar Dansat KVOT Svanroller Jaha, nu får det alltså inte finnas någon svanroll som kandidaterna inte dansat: SELECT D.Namn FROM DANSARE D WHERE NOT EXISTS (SELECT R.RollNam FROM ROLL R WHERE R.BalettNamn= Svansjön AND R.RollNamn NOT IN (SELECT RI.Roll FROM ROLLINNEHAV RI WHERE Balett= Svansjön AND RI.Dansare=D.Namn)
ÖVNING 15 Betrakta relationsdatabasschemat i föregående uppgift och formulera följande frågor i a) SQL b) Relationsalgebra 8) Hur många personer får plats i den sal som ligger närmast Pelarsalen? (Ta hänsyn till svårigheten att en viss sal kan finnas representerad som antingen Sal1 eller Sal2 eller båda delar). Salarna := PI (SalsId, Maxantal_personer, Längd) (SIGMA (SalsId=Sal1ANDSal2= Pelarsalen )OR(Salsid=Sal2ANDSal1= Pelarsalen )(AVSTÅND X SAL)) Kortast := F Min (Längd) (Salarna) Svar PI (Salsid, Maxlängd)(SIGMA (Salarna.Längd=Kortast.Längd)(Salarna X Kortast)) CREATE VIEW temp_sal AS (SELECT Salsid, Maxantal, Längd FROM Sal, AVSTÅND WHERE ((SalsID = Sal1 AND Sal2= Pelarsalen ) OR (SalsId = Sal2 AND Sal1= Pelarsalen)) SELECT SalsID, Maxantal FROM temp_sal WHERE Längd = (SELECT min(längd) FROM tempsal) Alternativ: CREATE VIEW PELARGRANNAR AS ((SELECT Sal2 AS Sal, Längd FROM AVSTÅND WHERE Sal1= Pelarsalen ) UNION (SELECT Sal1 AS Sal, Längd FROM AVSTÅND WHERE Sal2= Pelarsalen )) SELECT SalsId, Maxantal FROM PELARGRANNAR, SAL WHERE SalsID=Sal AND Längd = (SELECT min(längd) FROM PELARGRANNAR)
9) Vilka dansare har dansat i åtminstone samma baletter som Kanneli Kallanko? Dansat_i_balett(Dansare, Balett) PI (Dansare, Balett) (ROLLINNEHAV) Kannelli_baletter(Balett) PI (Balett) (SIGMA Dansare= Kanelli Kallanko (ROLLINNEHAV)) Svar Dansat_i_balett KVOT Kanelli_baletter SELECT D.Namn FROM DANSARE D WHERE D.Namn NOT = Kannelli Kallanko AND NOT EXISTS /* Får inte finnas ngn balett som Kannelli dansat som inte jag har dansat */ (SELECT R1.Balett FROM ROLLINNEHAV R1 WHERE R1.Dansare = Kannelli Kallanko AND R1.Balett NOT IN (SELECT R2.Balett FROM ROLLINNEHAV R2 WHERE R2.Dansare = D.Namn))
10) Vilka dansare har dansat i exakt samma baletter som Kanneli Kallanko? Dansat_i_balett (Dansare, Balett) PI (Dansare, Balett) (ROLLINNEHAV) Kannelli_baletter(Balett) PI (Balett) (SIGMA Dansare= Kanelli Kallanko (ROLLINNEHAV)) Ej_Kanneli_baletter(Balett) PI (Balett) (BALETT) Kannelli_baletter Dansat_i_nåt_mer PI (Dansare) (Ej_Kannelli_balleter NATURAL JOIN Dansat_i_balett) Svar (Dansat_i_balett KVOT Kanelli_baletter) Dansat_i_nåt_mer SELECT D.Namn FROM DANSARE D WHERE D.Namn NOT = Kannelli Kallanko AND NOT EXISTS /* Får inte finnas ngn balett som Kannelli dansat som inte jag har dansat */ (SELECT R1.Balett FROM ROLLINNEHAV R1 WHERE R1.Dansare = Kannelli Kallanko AND R1.Balett NOT IN (SELECT R2.Balett FROM ROLLINNEHAV R2 WHERE R2.Dansare = D.Namn)) AND NOT EXISTS /* Får inte finnas ngn balett som jag dansat som inte Kanelli har dansat */ (SELECT R1.Balett FROM ROLLINNEHAV R1 WHERE R1.Dansare = D.Namn AND R1.Balett NOT IN (SELECT R2.Balett FROM ROLLINNEHAV R2 WHERE R2.Dansare = Kanelli Kallanko ))
11) Vilka (par av) dansare har dansat i exakt samma baletter? En generell relationsalgebra lösning saknas än så länge, alla förslag mottages ödmjukt. Här kommer ett (courtesy of Anders Condradi) : Definiera först några hjälpsamma mängder: U: Alla möjliga par av dansare (a, b). G: Alla par av dansare (a, b) som har dansat i någon gemensam balett. P: Alla par av dansare (a, b) där a har dansat i någon balett som inte b har dansat i.!p: Alla par av dansare (a, b) där det inte finns någon balett som a har spela i som inte b har dansat i. Q: Alla par av dansare (a, b) där b har dansat i någon balett som inte a har dansat i.!q: Alla par av dansare (a, b) där det inte finns någon balett som b har spela i som inte a har dansat i. Den sökta mängden X definieras som mängden av alla par (a, b) där a och b har dansat i exakt samma baletter. Det kan även ses som att för att ett par (a, b) ska få vara med i X måste a och b ha spelat i minst en gemensam balett och det får inte finnas några baletter som a spelat i men inte b och det får inte finnas några baletter som b spelat i men inte a. Mängden av alla sådana par fås enkelt genom X <- G intersection!p intersection!q. Det enda som nu återstår är att konstruera mängderna G,!P och!q. För att göra det definierar vi först ett par hjälprelationer: Ar(A, balett) <- pi_{dansare, Balett}(ROLLINNEHAV)!Ar(A, balett) <- pi_{dansare}(rollinnehav) * pi_{balett}(rollinnehav) - - Ar Br(B, balett) <- Ar!Br(B, balett) <-!Ar Sedan konstruerar vi även de hjälpmängder vi behöver: U <- rho_{a}(pi_{dansare}(rollinnehav)) * * rho_{b}(pi_{dansare}(rollinnehav)) P <- pi_{a, B}(Ar join_{ar.balett=!br.balett}!br) Q <- pi_{a, B}(!Ar join_{!ar.balett=br.balett} Br) Sedan fås G,!P och!q enkelt:
G <- pi_{a, B}(Ar join_{ar.balett=br.balett} Br)!P <- U - P!Q <- U - Q Så var det klart. --------------------------------------------------------------------------------- SQL: SELECT D1.Namn, D2.Namn FROM DANSARE D1, DANSARE D2 WHERE D1.Namn NOT = D2.Namn AND NOT EXISTS /* Får inte finnas ngn balett som D1 dansat som inte D2 har dansat */ (SELECT R1.Balett FROM ROLLINNEHAV R1 WHERE R1.Dansare = D1.Namn AND R1.Balett NOT IN (SELECT R2.Balett FROM ROLLINNEHAV R2 WHERE R2.Dansare = D2.Namn)) AND NOT EXISTS /* Får inte finnas ngn balett som D2 dansat som inte D1 har dansat */ (SELECT R1.Balett FROM ROLLINNEHAV R1 WHERE R1.Dansare = D2.Namn AND R1.Balett NOT IN (SELECT R2.Balett FROM ROLLINNEHAV R2 WHERE R2.Dansare = D1.Namn))