University of Southern Denmark Department of Mathematics and Computer Science Databaser Obligatorisk opgave 1 Afleveres senest: Lørdag d. 23. marts kl 23.59
Introduction Denne obligatoriske opgave indeholder 3 opgaver, der alle skal besvares. Opgaven skal besvares individuelt. Besvarelsen afleveres via Blackboard senest lørdag d. 23. marts kl 23.59. Din besvarelse skal uploads som én pdf fil, hvor dit navn tydeligt fremgår af den første side. Du skal uddybe dine besvarelser, med beskrivende tekst, men du behøver ikke at gentage opgavens tekst i din besvarelse. Vejledende pointtal Der kan opnåes i alt 100 point, fordelt således: Opgave Point Bemærkninger 1.1 10 1.2 10 1.3 10 2.1 7 2.2 7 2.3 8 2.4 8 3.1.1 10 Kun halvt point hvis der ikke argumenteres for at der ikke er andre keys 3.1.2 10 3.2.1 10 Kun halvt point hvis der ikke argumenteres for at der ikke er andre keys 3.2.2 10 1 Relational Algebra Betragt følgende relationer: Ingrediens(ingrediens id, inavn, pris) Opskrift(opskrift id, rnavn, type, portioner) Indeholder(opskrift id, ingrediens id, mængde) Skriv med relationel algebra eller tegn et træ med relationelle operatorer, der besvarer følgende spørgsmål 1. En liste med ingredienser og mængder for opskriften Frikadeller 2. En liste med alle opskriftnavne, for opskrifter der kun indeholder ingredienser der koster mindre end 20 3. Opskriftnavn for opskrifter der indeholder Bacon men ikke Champignon 2
1.1 Først joines opskrift med indeholder og gemmes i R 1, hvor opskrift id matcher R 1 := Opskrift Opskrift.opskrift id=indeholder.opskrift id Indeholder Så joines Ingrediens på hvor ingrediens id matcher. R 2 := R 1 Opskrift.ingrediens id=ingrediens.ingrediens id Ingrediens Til sidst vælger vi alle rækker, hvor opskrift navnet er Frikadeller, og tager ingrediens navn og mængde ud med en projektion. π Ingrediens.inavn,Ingrediens.mængde (σ Opskrift.rnavn= Frikadeller (R 2)) 1.2 Vi vil gerne have alle opskrifter undtagen dem der har ingredienser dyrere end 20. Vi finder derfor listen af opskrifter der har ingredienser dyrere end 20 først. Som før joiner vi alle tabellerne sammen med matchende id ere. R 1 := Opskrift Opskrift.opskrift id=indeholder.opskrift id Indeholder R 2 := R 1 Opskrift.ingrediens id=ingrediens.ingrediens id Ingrediens Så herfra vælges alle opskrifts id er med ingredienser dyrere end 20 R 3 := π Opskrift.opskrift id (σ Ingrediens.pris>20 (R 2 )) Nu laver vi en liste af opskrifts id er der ikke har dyre ingredienser. R 4 := π Opskrift.opskrift id (Opskrift) R 3 Og til sidst vil vi gerne have navnene på opskrifterne π Opskrift.rnavn (Opskrift Opskrift.opskrift id=r4.opskrift id R 4 ) 1.3 Som før joiner vi alle tabellerne sammen med matchende id ere. R 1 := Opskrift Opskrift.opskrift id=indeholder.opskrift id Indeholder R 2 := R 1 Opskrift.ingrediens id=ingrediens.ingrediens id Ingrediens 3
Først finder vi alle opskrifter med bacon (R 3 ), og dernæst alle opskrifter med champignon (R 4 ) R 3 := π Opskrift.opskrift id,opskrift.rnavn (σ Ingrediens.inavn= Bacon (R 2)) R 4 := π Opskrift.opskrift id,opskrift.rnavn (σ Ingrediens.inavn= Champignon (R 2)) Og til sidst vil vi gerne have navnene på opskrifterne der indeholder bacon, men ikke champignon π Opskrift.rnavn (R 3 R 4 ) 2 SQL Betragt igen relationerne fra spørgsmål 1: 2.1 1. Skriv SQL der opretter tabellerne, med fornuftigt valgte typer, keys mm. 2. Skriv en SQL forespørgsel der vælger alle opskriftsnavne, hvis navne starter med Is 3. Skriv en SQL forespørgsel, der fordobler antallet af portioner for alle opskrifter med typen Forret 4. Skriv en SQL forespørgsel, der for hver opskrift angiver antallet af forskellige ingredienser den indeholder Jeg antager at opskrifter og ingredienser ikke har navne længere end 20 bogstaver, type ikke længere end 10, samt at mængde, pris og antal ikke kan være negativt. Jeg antager også at to opskrifter ikke kan have samme navn. CREATE TABLE Ingrediens ( ingrediens_id INT PRIMARY KEY, inavn VARCHAR(20) UNIQUE, pris REAL CHECK ( pris >= 0) ); CREATE TABLE Opskrift( opskrift_id INT PRIMARY KEY, rnavn VARCHAR(20), type VARCHAR(10), portioner INT CHECK ( portioner >= 0) ); 4
CREATE TABLE Indeholder( opskrift_id INT, ingrediens_id INT, mængde REAL CHECK ( mængde >= 0), PRIMARY KEY (opskrift_id, ingrediens_id), FOREIGN KEY (opskrift_id) REFERENCES Opskrift(opskrift_id), FOREIGN KEY (ingrediens_id) REFERENCES Ingrediens(ingrediens_id) ); 2.2 SELECT rnavn FROM Opskrift WHERE rnavn LIKE %is ; 2.3 UPDATE Opskrift SET portioner = 2 * portioner WHERE type = Forret ; 2.4 SELECT O.rnavn, COUNT(*) FROM opskrift O INNER JOIN indeholder I ON O.opskrift_id = I.opskrift_id GROUP BY O.rnavn; 3 Normalization Part 1 Betragt relationen R (A B C D E) med functional dependencies: F := { D B, E C, B A, E D }. 1. Find alle keys, og argumenter for at der ikke kan være andre. 2. Er R på Boyce-Codd Normal Form? Hvis den er, argumenter hvorfor, og hvis ikke, split R op i mindre relationer, til BCNF er overholdt, samt afgør om decompositionen er dependency preserving. 5
Part 2 Betragt relationen R (A B C D E) med functional dependencies: F := { B A, D C, B E, D E }. 1. Find alle keys, og argumenter for at der ikke kan være andre. 2. Er R på Boyce-Codd Normal Form? Hvis den er, argumenter hvorfor, og hvis ikke, split R op i mindre relationer, til BCNF er overholdt, samt afgør om decompositionen er dependency preserving. 3.1.1 Vi undersøger først closure af attributterne, og finder at: A + := A B + := A B C + := C D + := A B D E + := A B C D E Vi kan herfra se at E er en key. Vi bemærker at ingen FD definerer E, så den skal derfor indgå i en vilkårlig key. På grund af at en key skal være minimal er E den eneste key der er for R. Til senere brug er det ok at betragte alle delmængder. 3.1.2 R er ikke på BCNF, da både D B og B A er en overtrædelse (deres venstreside er ikke en superkey, da den ikke indeholder E). Vi bliver derfor nødt til at dele relationen op. Vi vælger at bruge D B til at dele R, og får: R 1 = ABD og R 2 = CDE For at bestemme om R 1 og R 2 er på BCNF, skal vi først bestemme deres key og deres FD. Det kræver at vi kender alle FD s i R. Ud fra closures af de enkelte delmængder af attributter finder vi at D A, E A, og E B også er FD i R. Ifølge algoritme 3.12 har vi følgende FD for de to nye relationer: R 1 : { B A, D B, D A } R 2 : { E C, E D } For R 2 ses let at E er key, og at ingen FD s overtræder BCNF. For R 1 finder vi closures: A + := A B + := A B D + := A B D 6
Vi kan nu se at D er key, og da A og B ikke definerer D, vil den være med i enhver key. Det betyder at R 1 ikke er på BCNF, da B A er en konflikt, fordi A ikke er en superkey. Vi deler derfor R 1 i AB og BD, som fordi de kun indeholder to attributter er på BCNF. Vi ender på BCNF med følgende opdeling af relationen: AB, BD og CDE. Ved at se på de originale FD, kan vi konstatere at alle kan checkes i én relation, og vi konstaterer at decompositionen er dependency preserving. 3.2.1 Vi undersøger først closure af attributterne, og finder at: A + := A B + := A B E C + := C D + := C D E E + := E AB + := A B E AC + := A C AD + := A C D E AE + := A E BC + := A B C E BD + := A B C D E BE + := A B E CD + := C D E CE + := C E DE + := C D E... Da ingen FD definerer B eller D, og de tilsammen er en key, kan vi konkludere at både B og D skal indgå i enhver key, og BD er derfor den eneste. 3.2.2 R er ikke på BCNF, da alle FD s er i konflikt (deres venstreside er ikke en superkey, da den ikke indeholder hele BD). Vi bliver derfor nødt til at dele relationen op. Vi vælger at bruge B A til at dele R, og får: R 1 = ABE og R 2 = BCD Vi ser nu på på de tilhørende FD ere (der er reduceret): R 1 : { B A, B E } R 2 : { D C } Vi kan konstatere at B er key for R 1 og at BD er key for R 2. R 1 er på BCNF, da der ikke er konflikter, men D C er en konflikt for R 2. Vi splitter derfor R 2 i CD og BD, som begge er på BCNF pga de kun har to attributter. Vi ender derfor med den følgende decomposition: ABE, CD og BD. 7
Da vi ikke kan checke D E uden at joine to tabeller er decompositionen ikke dependency preserving. 8