informatica databases & SQL - antwoorden
Op dit lesmateriaal is een Creative Commons licentie van toepassing. 2010 Remie Woudt remie.woudt@gmail.com 2013 François Vonk (XAMP vervangen door USBWebserver en minor edits)
Databases Opdracht 1-3 Tweede dier toevoegen. En dan staan er heel veel dubbele gegevens in de tabel, namelijk alle NAW gegevens van mevrouw Paay. Dus stel dat mevrouw Paay een verhuizing doorgeeft dan moet deze op meerdere plekken (records) worden doorgevoerd met alle mogelijk fouten van dien. Het wordt nog erger als mevrouw maar liefst 4 of 5 dieren heeft. Opdracht 1-6 Dit veld moet niet opgehoogd worden als er een nieuw dier bij komt. Het kan immers een dier zijn van een reeds bestaande klant. De waarde van dit veld moet uit de klantentabel gehaald worden. Opdracht 1-7 Hoofdstuk Databases 1
data normalisatie (vwo) Opdracht 2-1 Stap 1 Het eerste wat ik doe is de gegevens die bij elkaar horen ook bij elkaar zetten. Eigenlijk begin ik dus met de 3th NF. Alhoewel ik nog geen sleutelveld heb ingevoerd. Maar op deze manier krijg je wat overzicht en heb je een beeld waar je eventueel een sleutelveld nodig hebt. Ik geef de groep gegevens meteen een naam. Overigens is niet altijd de precieze bedoeling van een tabel duidelijk en het kan dus voorkomen dat je enigszins andere indeling maakt. Klant Naam voorletters en voorvoegsel Adres Postcode Woonplaats Telefoon Dier naam van het dier soort dier Ras Geboortedatum Gewicht Kleur Behandeling behandelingsdatum en eventueel de tijd omschrijving van de behandeling (vrije tekstveld) Artikelen Artikel registratienummer van het artikel verpakkingseenheid van het artikel prijs van het artikel Vervolgbehandelingen eventuele vervolgbehandeling van het artikel (bijvoorbeeld herhalingsentingen) datum vervolgbehandelingen Verrichtingen Verrichting prijs van de verrichting Anamneses anamnese (beschrijving van het ziekte beeld) 2 data normalisatie (vwo)
Stap 2 Nu ga ik daar sleutelvelden aan toe voegen. Klant Klantnummer Naam voorletters en voorvoegsel Adres Postcode Woonplaats Telefoon Dier diernummer naam van het dier soort dier Ras Geboortedatum Gewicht Kleur Behandeling behandelingnummer behandelingsdatum en eventueel de tijd omschrijving van de behandeling (vrije tekstveld) Artikelen artikelnummer Artikel registratienummer van het artikel verpakkingseenheid van het artikel prijs van het artikel Vervolgbehandelingen vervolgbehandelingnummer eventuele vervolgbehandeling van het artikel (bijvoorbeeld herhalingsentingen) datum vervolgbehandelingen Verrichtingen verrichtingnummer Verrichting prijs van de verrichting Anamneses anamnesenummer anamnese (beschrijving van het ziekte beeld) Stap 3 Nu we een voorlopige indeling hebben kunnen we gaan kijken in hoeverre voldaan wordt aan de eerste 3 regels van de normalisatie. 1st NF: Ieder veld bestaat uit een enkele waarde (geen combinatie van waarden) en iedere tabel mag geen velden bevatten die herhaald worden Als je goed kijkt zie je hier tenminste één veld dat bestaat uit meer dan één waarde, namelijk voorletters en voorvoegsel. Nu zijn deze niet erg belangrijk omdat je dit toch vrijwel altijd samen zult willen gebruiken. Dus je mag dit gerust beschouwen als een enkele waarde. De tabellen bevatten op het eerste gezicht ook geen herhalingen. Als je bijvoorbeeld weet dat er bij het gebruik van bepaalde artikelen zoals entingen maximaal 3 herhalingsbehandelingen nodig zijn zou je kunnen overwegen in de artikeltabel de velden herhaling1, herhaling2 en herhaling3 toe te voegen. Maar dat is in strijd met de 1st NF. Stap 4 Op naar de 2nd NF. 2nd NF: Zorg ervoor dat ieder veld functioneel afhankelijk is van het (gehele) sleutelveld. Wanneer een sleutelveld bestaat uit meerdere velden en een veld in de tabel is slechts functioneel afhankelijk van één van die velden uit dat sleutelveld, plaats dan dat veld in een afzonderlijke tabel. Een belangrijk deel hebben we hier al opgelost door te kiezen voor een onafhankelijke nummering van de sleutelvelden. De sleutelvelden hebben zelf geen betekenis en dat is de meest Hoofdstuk Databases 3
ideale situatie. Een sleutelveld bestaat dus op deze manier nooit uit meerdere delen dus het tweede deel van de 2nd NF is niet van toepassing. Het functioneel afhankelijk zijn van het gehele sleutelveld is een wat lastiger begrip. Maar als je in het begin een goede indeling hebt gemaakt is dat vrijwel altijd wel het geval. Alles wat in de tabel klant staat hoort ook alleen maar bij die specifieke klant. Stap 5 Tenslotte de 3th NF 3th NF: Verwijder velden die niet functioneel afhankelijk zijn van een sleutelveld. Zoals al eerder aangegeven doe je dat in feite door de bulk gegevens te splitsen in groepjes gegevens die bij elkaar horen. Kortom, we houden de tabelstructuur over die we in punt 2 al opgesteld hebben. Maar daarmee zijn we er nog niet. Stap 6 Tussen de tabellen bevinden zich relaties. We gaan die voor iedere tabel uitzoeken. Klant heeft een relatie met de tabel Dier Eén klant kan meerdere dieren hebben Een dier heeft maar één eigenaar (klant) Dit is een één (klant) op veel (dier) relatie Het sleutelveld van de klant (de één zijde) wordt toegevoegd als vreemde sleutel in de tabel dier (de veel zijde) Dier heeft een relatie met de tabel Behandeling Eén dier kan meerdere behandelingen hebben Eén behandeling heeft maar betrekking op één dier Dit is een één (dier) op veel (behandeling) relatie Het sleutelveld van het dier (de één zijde) wordt toegevoegd als vreemde sleutel in de tabel behandeling Behandeling heeft een relatie met Artikel Eén behandeling kan meerdere artikelen omvatten Eén artikel kan in meerdere behandelingen voorkomen Dit is een veel op veel relatie Dat betekent dat er een tussentabel moet komen bestaande uit minimaal de beide sleutelvelden van de tabellen die deze relatie hebben Artikel heeft een relatie met Vervolgbehandelingen Eén artikel kan meerdere vervolgbehandelingen hebben Eén vervolgbehandeling hoort bij één artikel Dit is een één (artikel) op veel (vervolgbehandelingen) relatie Het sleutelveld van het artikel (de één zijde) wordt toegevoegd als vreemde sleutel in de tabel vervolgbehandelingen (de veel zijde) Behandeling heeft een relatie met Verrichtingen Eén behandeling kan meerdere verrichtingen omvatten Eén verrichting kan in meerdere behandelingen voorkomen Dit is een veel op veel relatie Dat betekent dat er een tussentabel moet komen bestaande uit minimaal de beide sleutelvelden van de tabellen die deze relatie hebben 4 data normalisatie (vwo)
Behandeling heeft een relatie met Anamnese Eén behandeling kan meerdere anamneses omvatten Eén anamnese kan in meerdere behandelingen voorkomen Dit is een veel op veel relatie Dat betekent dat er een tussentabel moet komen bestaande uit minimaal de beide sleutelvelden van de tabellen die deze relatie hebben Hier de uitwerkingen van deze relaties: Klant Klantnummer Naam voorletters en voorvoegsel Adres Postcode Woonplaats Telefoon Dier Diernummer Klantnummer naam van het dier soort dier Ras Geboortedatum Gewicht Kleur Behandeling Behandelingnummer Diernummer behandelingsdatum en eventueel de tijd omschrijving van de behandeling (vrije tekstveld) artikelnummer eventuele vervolgbehandeling van het artikel (bijvoorbeeld herhalingsentingen) datum vervolgbehandelingen tussentabel behandeling-verrichting behandelingnummer verrichtingennummer Verrichtingen Verrichtingennummer Verrichting prijs van de verrichting tussentabel behandeling-anamnese behandelingnummer anamnesenummer Anamneses Anamnesenummer anamnese (beschrijving van het ziekte beeld) tussentabel behandeling-artikelen behandelingnummer artikelnummer Artikelen Artikelnummer Artikel registratienummer van het artikel verpakkingseenheid van het artikel prijs van het artikel Vervolgbehandelingen Vervolgbehandelingennummer Hoofdstuk Databases 5
Opdracht 2-2 Nu we zover zijn is het niet al te moeilijk meer een strokendiagram te maken. 6 data normalisatie (vwo)
SQL Opdracht 3-1 Bestand winkel.sql importeren Opdracht 3-2 Voer de eerste SQL opdracht uit. Opdracht 3-3 Met DISTINCT krijg je iedere provincie maar één keer te zien, zonder DISTINCT zie je bepaalde provincies meerdere malen. Opdracht 3-4a SELECT klantnummer, artikel, prijs WHERE klantnummer = 10449; Opdracht 3-4b WHERE artikel = 'Tent'; Opdracht 3-4c SELECT klantnummer, order_datum, artikel WHERE artikel LIKE 'S%'; Opdracht 3-4d SELECT DISTINCT artikel ; Opdracht 3-4e WHERE provincie LIKE 'F%'; Opdracht 3-4f SELECT klantnummer WHERE voornaam = 'Jan;
Opdracht 3-4g SELECT klantnummer, artikel, prijs WHERE artikel LIKE ' '; Opdracht 3-5 Deze opdracht zal alle regels uit de tabel Bestelde_artikelen opleveren waar de artikelnaam Paraplu is en ook alle regels waarbij de prijs groter is dan of gelijk aan 5. Opdracht 3-6a SELECT klantnummer, order_datum, artikel WHERE (artikel <> 'Sneeuwschoenen') AND (artikel <> 'Oorwarmers'); Opdracht 3-6b SELECT artikel, prijs WHERE (artikel LIKE 'S%') OR (artikel LIKE 'P%') OR (artikel LIKE 'F%'); Opdracht 3-6c WHERE provincie = 'Friesland' OR provincie = 'Gelderland'; Opdracht 3-6d WHERE provincie <> 'Friesland' AND provincie <> 'Gelderland'; of: WHERE NOT (provincie='friesland' OR provincie = 'Gelderland'); Opdracht 3-7a SELECT order_datum, artikel, prijs WHERE prijs BETWEEN 10 AND 80; Opdracht 3-7b SELECT voornaam, woonplaats, provincie WHERE provincie IN ('Friesland', 'Flevoland', 'Noord-Holland', 'Zuid-Holland', 'Utrecht');
Opdracht 3-7c WHERE hoeveelheid BETWEEN 1 AND 3; of WHERE hoeveelheid IN(1,2,3); Opdracht 3-7d WHERE hoeveelheid NOT BETWEEN 1 AND 3; of WHERE hoeveelheid NOT IN(1,2,3); Opdracht 3-8a SELECT MAX(prijs) ; Opdracht 3-8b SELECT AVG(prijs) WHERE order_datum LIKE '%-12-%'; Opdracht 3-8c SELECT COUNT(*) WHERE artikel = 'Zaklantaarn'; Opdracht 3-8d SELECT MIN(prijs) WHERE artikel = 'Tent'; Opdracht 3-8e SELECT COUNT(*) WHERE order_datum LIKE '%-01-%';
Opdracht 3-8f SELECT COUNT(*) WHERE achternaam LIKE 'G%'; Opdracht 3-8g SELECT AVG(prijs) WHERE artikel = 'Zaklantaarn'; Bovenstaande is correct als de definitie van prijs is dat het de prijs van het artikel en niet de order is. Anders is deze oplossing niet geheel juist, omdat het aantal bestelde zaklantaarns er niet in mee wordt genomen. Dan is de correcte oplossing: SELECT AVG(prijs/hoeveelheid) WHERE artikel = 'Zaklantaarn'; Opdracht 3-9a SELECT artikel, SUM(prijs)/SUM(hoeveelheid) GROUP BY artikel; Opdracht 3-9b SELECT ROUND(prijs) WHERE artikel = 'Eenwieler'; Liever afronden op twee decimalen? SELECT ROUND(prijs,2) WHERE artikel = 'Eenwieler'; Opdracht 3-9c SELECT ROUND(SUM(prijs),2) WHERE artikel = 'Eenwieler'; Opdracht 3-9d SELECT MIN(prijs) WHERE prijs >= 100; Opdracht 3-10a SELECT voornaam, achternaam, woonplaats ORDER BY achternaam ;
Opdracht 3-10b SELECT voornaam, achternaam, woonplaats ORDER BY achternaam DESC; Opdracht 3-10c SELECT artikel, prijs WHERE prijs > 10 ORDER BY prijs; Opdracht 3-10d ORDER BY klantnummer, prijs DESC; Opdracht 3-11 Opdracht uitvoeren Opdracht 3-12a SELECT provincie, COUNT(*) GROUP BY provincie; Opdracht 3-12b SELECT artikel, MAX(prijs), MIN(prijs) GROUP BY artikel; Opdracht 3-12c SELECT klantnummer, COUNT(klantnummer), SUM(hoeveelheid * prijs) GROUP BY klantnummer; Opdracht 3-12d SELECT klantnummer, COUNT(klantnummer), SUM(hoeveelheid * prijs) WHERE order_datum LIKE '%-01-%' GROUP BY klantnummer; Opdracht 3-13a SELECT provincie, COUNT(provincie) GROUP BY provincie HAVING COUNT(provincie) > 1;
Opdracht 3-13b SELECT artikel, MAX(prijs), MIN(prijs) GROUP BY artikel HAVING MAX(prijs) > 190; Opdracht 3-13c SELECT klantnummer, COUNT(klantnummer), SUM(hoeveelheid * prijs) GROUP BY klantnummer HAVING COUNT(klantnummer) > 1; Opdracht 3-13d SELECT artikel, MAX(prijs), MIN(prijs) GROUP BY artikel HAVING SUM(hoeveelheid) > 3; Opdracht 3-13e SELECT artikel, MAX(prijs), MIN(prijs) GROUP BY artikel HAVING MAX(prijs) > 100 ORDER BY artikel DESC; Opdracht 3-14a
Opdracht 3-14b Nee, dit is goed gedefinieerde database structuur. Er zijn geen primaire sleutels. Of de tabel bestelde_artikelen wel of niet goed genormaliseerd is is open voor discussie. Als 100 klanten 1 slaapzak bestellen op dezelfde dag dan krijg je nogal wat duplicatie in je tabel. Wat is bovendien het veld prijs? Is dit de prijs van de order? Zijn er meerdere soorten tenten en hoe kan ik die onderscheiden? Kijk eens naar de twee tent verkopen en de prijs die bij het record hoort. Deze database structuur is nog verre van ideaal maar voldoende om query's mee te oefenen. Opdracht 3-15a SELECT K.klantnummer, voornaam, achternaam, order_datum, artikel, prijs K, bestelde_artikelen BA WHERE K.klantnummer = BA.klantnummer; Opdracht 3-15b SELECT K.klantnummer, voornaam, achternaam, order_datum, artikel, prijs K, bestelde_artikelen BA WHERE K.klantnummer = BA.klantnummer ORDER BY provincie DESC; Opdracht 3-15c SELECT BA.* BA, klanten K WHERE BA.klantnummer = K.klantnummer AND provincie = 'Utrecht'; of SELECT BA.* BA, klanten K WHERE BA.klantnummer = K.klantnummer AND woonplaats = 'Utrecht'; Opdracht 3-15d SELECT K.* K, bestelde_artikelen BA WHERE K.klantnummer = BA.klantnummer AND artikel = 'Zaklantaarn'; Vanaf hier gaat het over sub-query's (vwo) Opdracht 3-16a SELECT DISTINCT klantnummer WHERE prijs = (SELECT MIN(prijs) );
Opdracht 3-16b SELECT DISTINCT klantnummer WHERE prijs < (SELECT AVG(prijs) ); Opdracht 3-16c SELECT COUNT(*) WHERE prijs < (SELECT AVG(prijs) ); Opdracht 3-16d SELECT COUNT(*) FROM (SELECT DISTINCT klantnummer WHERE prijs < (SELECT AVG(prijs) )) AS R; Opdracht 3-17a SELECT voornaam, achternaam WHERE klantnummer IN (SELECT DISTINCT klantnummer WHERE prijs > (SELECT AVG(prijs) )); Opdracht 3-17b SELECT voornaam, achternaam K, bestelde_artikelen BA WHERE K.klantnummer = BA.klantnummer AND prijs > (SELECT AVG(prijs) ); Opdracht 3-18a SELECT artikel, SUM(hoeveelheid) AS S GROUP BY artikel HAVING S >= ALL(SELECT SUM(hoeveelheid) GROUP BY artikel);
Opdracht 3-18b SELECT artikel, SUM(hoeveelheid) AS S GROUP BY artikel HAVING NOT(S < ANY(SELECT SUM(hoeveelheid) GROUP BY artikel)); Opdracht 3-18c SELECT klantnummer, voornaam, achternaam WHERE NOT (klantnummer = ANY (SELECT distinct klantnummer )); Opdracht 3-18d SELECT klantnummer, voornaam, achternaam WHERE NOT (klantnummer IN (SELECT distinct klantnummer ));