Professional Documents
Culture Documents
0708database Uitwerkingen
0708database Uitwerkingen
Opgave 1b
Van sommige boeken zijn meerdere exemplaren aanwezig. Voor de bibliotheek is het
belangrijk te weten welk exemplaar van elk boek aan welke leerling is uitgeleend. Vandaar de
kolom EXNR in uitleningen. De tabel Reserveringen heeft deze kolom niet, want als een
leerling een boek wil reserveren dan doet hij of zij dat uitsluitend op titel.
Opgave 1c
De kolom BOEKNR staat in de tabel Reserveringen. Als je wilt weten welk boek daarbij
hoort kun je dat aan de hand van de kolom BOEKNR in de tabel Boeken opzoeken.
De kolom AUTEURNR staat in de tabel Boeken. Als je wilt weten welke schrijver daarbij
hoort kun je dat aan de hand van de kolom AUTEURNR in de tabel Auteurs opzoeken.
Opgave 2a
Opgave 2b
Opgave 2c
Opgave 3a
Opgave 3b
Opgave 4a
Opgave 4c
Opgave 4d Eerst een query maken om het auteurnummer van de schrijver te vinden.
Probleem is dat je niet precies weet hoe de schrijver heet. Gebruik dus LIKE.
SELECT TITEL
FROM BOEKEN
WHERE AUTEURNR = 62
Opgave 4e
SELECT TITEL
FROM BOEKEN
WHERE AUTEURNR = 92
Opgave 5a
Opgave 5c
SELECT TITEL
FROM BOEKEN
WHERE TITEL LIKE '*vos*'
Opgave 6a
Opmerking: deze query levert geen resultaat op: blijkbaar wonen er geen leerlingen in de
Julianaweg. Je kunt het controleren door de volgende regel weg te laten:
Opgave 6b
Opgave 6c
Opgave 7b
De laatste eis PLAATS = 'Bunnik' staat los van de eis KLAS = '5b' waardoor de leerlingen
uit Bunnik ook in andere klassen kunnen zitten.
Opgave 7c
SELECT *
FROM LEERLINGEN
WHERE (
KLAS = '5b' AND PLAATS = 'Utrecht'
)
OR PLAATS = 'Bunnik'
Opgave 7d
SELECT *
FROM LEERLINGEN
WHERE KLAS = '5b'
AND (
PLAATS = 'Utrecht' OR PLAATS = 'Bunnik'
)
Opgave 7e
7 * 5 + 2 = 35 + 2 = 37
7 * (5 + 2) = 7 * 7 = 49
Dit zijn alle leerlingen die voldoen aan de voorwaarde (KLAS LIKE ’5*’ AND
GESLACHT= ‘v’) óf (OR KLAS=’5a’).
Nu moet het een leerling uit een 5e klas zijn EN een meisje uit 5a (begrijp je dat het eerste
deel nu overbodig geworden is? In het tweede deel moet het immers per se klas 5a zijn)
Opgave 8a
Opgave 9b
Eerst een query maken om te kijken hoe oud Jantine de Bakker nu eigenlijk precies is:
De eerste eis is dat de jongen ouder is dan haar, maar ook weer niet te oud, een jaar ouder is in
orde.
De twee eis is wat soepeler: nu mag de jongen nog wel twee jaar ouder zijn, maar dan moet
hij bij haar in de buurt wonen. Haar postcode volgt uit de eerste query en is 3523 HZ.
De query wordt nu:
Opvallend is dat de tweede eis, dus het gedeelte na de OR, geen extra namen oplevert!
Let op: in openoffice moet je een andere datumnotatie gebruiken (zie de tip op de website)
Opgave 9a
SELECT MAX(BOETE)
FROM UITLENINGEN
Opgave 9b
SELECT AVG(BOETE)
FROM UITLENINGEN
Opgave 9c
SELECT MIN(GEB_DATUM)
FROM LEERLINGEN
SELECT MAX(GEB_DATUM)
FROM LEERLINGEN
Opgave 9d
SELECT COUNT(*)
FROM EXEMPLAREN
WHERE STATUS = 'in reparatie'
Opgave 10a
Opgave 10b
Opgave 10c
Opgave 10d
SELECT RUBRIEK, COUNT(*)
FROM BOEKEN
GROUP BY RUBRIEK
Opgave 11a
Voor de oudste leerling gebruik je dezelfde query en vervang je MIN door MAX.
SELECT *
FROM LEERLINGEN
WHERE GEB_DATUM =
(
SELECT MIN(GEB_DATUM)
FROM LEERLINGEN
)
OR GEB_DATUM =
(
SELECT MAX(GEB_DATUM)
FROM LEERLINGEN
)
Opgave 11b
‘WHERE GEB_DATUM =’ is beter, omdat je zeker weet dat er maar één minimale
geboortedatum bestaat.
Opgave 11c
SELECT TITEL
FROM BOEKEN
WHERE RUBRIEK = 'Nederlands'
AND BOEKNR IN
(
SELECT BOEKNR
FROM EXEMPLAREN
WHERE STATUS = 'in reparatie'
)
Opgave 11d
Opgave 11e
Opgave 12a
Opgave 12b
Als je ook zeker wilt weten dat er exemplaren zijn moet je ook de tabel exemplaren gebruiken
Opgave 12d
Opgave 12e
Als je wilt weten welke boeken aan leerlingen uit 6V uitgeleend zijn kan dat vrij eenvoudig.
SELECT *
FROM BOEKEN
WHERE RUBRIEK=’NEDERLANDS’
AND BOEKNR IN
(
SELECT BOEKNR
FROM UITLENINGEN
WHERE LLNR IN
(
SELECT LLNR
FROM LEERLINGEN
WHERE KLAS LIKE ‘6?’
)
)
Als je echter de gegevens van de leerlingen en de auteurs ook in het antwoord wilt hebben,
wordt het een ingewikkelde koppeling tussen 4 tabellen:
Opgave 13a
opgave 13b
SELECT *
FROM AUTEURS
WHERE AUTEURNR IN
(
SELECT AUTEURNR
FROM BOEKEN
GROUP BY AUTEURNR
HAVING COUNT(*)>5
)
opgave 13c
SELECT *
FROM BOEKEN
WHERE BOEKNR IN
(
SELECT BOEKNR
FROM UITLENING
GROUP BY BOEKNR
HAVING COUNT(*)>10
)
opgave 14a
SELECT *
FROM BOEKEN
WHERE NOT EXISTS
(
SELECT *
FROM UITLENINGEN
WHERE BOEKEN.BOEKNR=UITLENINGEN.BOEKNR
)
SELECT *
FROM BOEKEN
WHERE NOT (LLNR IN
(
SELECT LLNR
FROM UITLENINGEN
WHERE BOEKEN.BOEKNR=UITLENINGEN.BOEKNR
)
)
opgave 14b
SELECT *
FROM LEERLINGEN
WHERE NOT EXISTS
(
SELECT LLNR
FROM UITLENINGEN AS U, BOEKEN AS B
WHERE RUBRIEK=’NEDERLANDS’
AND U.BOEKNR=B.BOEKNR
)
SELECT *
FROM LEERLINGEN
WHERE NOT (LLNR IN
(
SELECT LLNR
FROM UITLENINGEN AS U, BOEKEN AS B
WHERE RUBRIEK=’NEDERLANDS’
AND U.BOEKNR=B.BOEKNR
)
)
opgave 15, maken we niet als views, maar gewoon als query
OPGAVE 15A
SELECT L.*,B
FROM LEERLINGEN AS L,
(
SELECT U.LLNR, SUM(U.BOETE) AS B
FROM UITLENINGEN AS U
GROUP BY U.LLNR
) AS S
WHERE L.LLNR=S.LLNR
opgave 15b
SELECT L.*,B
FROM LEERLINGEN AS L,
(
SELECT U.LLNR, SUM(U.BOETE) AS B
FROM UITLENINGEN AS U
GROUP BY U.LLNR
HAVING SUM(U.BOETE)>5
) AS S
WHERE L.LLNR=S.LLNR
opgave 15c
in reparatie
SELECT *
FROM BOEKEN
WHERE BOEKNR IN
(
SELECT BOEKNR
FROM EXEMPLAREN
WHERE STATUS='IN REPARATIE'
)
Vervang ‘in reparatie’ door ‘thuis’ en ‘uitgeleend’ voor de twee andere vragen
Je kunt ze ook ale drie in de where schrijven met een OR ertussen:
overslaan
opgave 17
opgave 17a
Let op: in openoffice moet je een andere datumnotatie gebruiken (zie de tip op de website)
opgave 18
SELECT EXNR
FROM EXEMPLAREN
WHERE BOEKNR=
(
SELECT BOEKNR
FROM BOEKEN
WHERE TITEL = "GIPH!"
)
AND STATUS = "THUIS";
opgave 19
We zoeken naar reserveringen die beschikbaar zijn sinds 21 februari of eerder, waarbij geen
uitlening hoort van na de 'datum_beschikbaar'. Dit laatste vinden met behulp van een
subquery met NOT EXISTS.
Helemaal nodig is deze subquery niet. Als een gereserveerd boek wordt opgehaald, moet de
status veranderd worden in 'opgehaald', en is de status van de reservering niet meer
'beschikbaar', maar een query zoals deze is toch wel aardig!
Als de query reserveringen vindt, volgt er een update in de database (reservering wordt
'vervallen') en een fysieke actie van de bibliothecaris (boek wordt teruggezet in de kast met
uitleenbare boeken). De verandering van status zorgt er ook voor dat een reservering niet twee
keer vervalt.
SELECT *
FROM RESERVERINGEN AS R
WHERE STATUS = "beschikbaar"
AND NOT EXISTS
(
SELECT *
FROM UITLENINGEN AS U
WHERE U.LLNR=R.LLNR
AND U.BOEKNR=R.BOEKNR
AND U.DATUM_UIT >= R.DATUM_BESCHIKBAAR
)
AND R.DATUM_BESCHIKBAAR <= #21-feb-2002#
Zonder subquery
opgave 20a
SELECT TITEL
FROM BOEKEN, UITLENINGEN
WHERE BOEKEN.BOEKNR = UITLENINGEN.BOEKNR
AND DATUM_UIT < #10-FEB-2006#
AND DATUM_TERUG IS NULL;
Let op: in openoffice moet je een andere datumnotatie gebruiken (zie de tip op de website)
opgave 20b
Voor boeknr 66 gaat het als volgt.
Let op: in openoffice moet je een andere datumnotatie gebruiken (zie de tip op de website)
Maar dat is niet goed genoeg!
Voor de aanmaningen moeten we drie weken terug naar 8 februari. Verder bevat de query
alleen veel joins om de gewenste gegevens op te halen.
Punt is overigens wel dat we aan de data niet kunnen zien of een uitlening al eerder is
aangemaand, er is geen status-variabele.
opgave 21
Opgave 22a
Een query met groeperen:
Als je meer gegevens van de auteur in de select wilt weergeven, moet e die wel ook in de
GROUP BY zetten.
opgave 22b
SELECT B.TITEL, A.ACHTERNAAM, COUNT(*)
FROM BOEKEN AS B, AUTEURS AS A, UITLENINGEN AS U
WHERE B.BOEKNR = U.BOEKNR
AND B.AUTEURNR=A.AUTEURNR
AND U.DATUM_UIT > {D '2004-09-01'}
GROUP BY B.BOEKNR, B.TITEL, A.ACHTERNAAM
Het mooist is 't natuurlijk om de query's te combineren en een rangschikking te maken van het
aantal uitleningen per exemplaar. Dit is makkelijk, omdat we de twee afzonderlijke query's al
hebben. Die heb je dan bijvoorbeeld bewaard onder de twee namen, die je bij FROM ziet
staan:
Query's als deze leiden tot vragen over query's die bijvoorbeeld een top-10 opleveren. Deze
zijn zeer ingewikkeld en daarom uit het boek van deel 2 weggelaten. Hier nog wel de uitleg
over hoe je deze query's zou kunnen maken.
Bij het genereren van tabellen die antwoord geven op vragen rond 'de 10 hoogste' of 'de
twintig kleinste' zou je kunnen denken aan iets van de vorm:
SELECT *
FROM <tabel>
ORDER BY <kolom waarvan je de top-10 wil zien>
HAVING RANK < 10
Regels zoals de laatste zijn alleen niet gedefinieerd in SQL. De gewenste tabel moet daarom
via een omweg geproduceerd worden.
Als voorbeeld bekijken we de cijfertabel 'CIJFER2', de tabel met drie kolommen uit hoofdstuk
12, opdracht 6. De vraag is: Geef de tien hoogste examenresultaten.
We beginnen met het maken van een join van deze tabel met zichzelf. Omdat we nu alle
namen dubbel hebben, moeten we AS gebruiken (niet behandeld in het boek) om de twee
kopieën te onderscheiden. Als voorwaarde stellen we dat het cijfer in de tweede kopie groter
of gelijk moet zijn aan het cijfer in de eerste kopie.
We krijgen nu een (lange) tabel met zes kolommen. De drie kolommen links zijn afkomstig
uit de kopie die we HOOFD genoemd hebben. In de kolom HOOFD.CIJFER zal het hoogste
cijfer maar één keer voorkomen (aangenomen dat alle examenresultaten verschillend zijn, het
verhaal wordt wat ingewikkelder, maar in principe niet anders als er dubbelen voorkomen).
De voorwaarde is dat het cijfer in de kopie BIJ groter of gelijk moet zijn. Alleen het hoogste
cijfer zelf voldoet aan deze voorwaarde. De rij met het hoogste cijfer komt in HOOFD dus
maar één keer voor, gekoppeld aan zichzelf.
Het op één na hoogste cijfer komt twee keer voor, gekoppeld aan zichzelf en aan de rij met het
hoogste resultaat. Nummer drie komt drie keer voor, enzovoorts.
Door te groeperen op de gegevens in HOOFD en te tellen hoe vaak de rijen voorkomen,
krijgen we rangnummers:
Wanneer de cijfers allemaal verschillen, krijgen we een tabel met de resultaten in volgorde,
met de rangnummers (uit de COUNT) 1, 2, 3, enzovoorts erbij. Met een HAVING selecteren
we de top-10: HAVING COUNT(*)<=10' bij het groeperen.
Wanneer er wel gelijken zijn, komen de ex-aequo-noteringen er ook uit, maar dan met het
laagste rangnummer: De cijfertabel geeft twee negens (elk met rangnummer 2), twee 8.9's (elk
met rangnummer 4) twee 8.7's (rang 6) en zes 8.6'en (rang 12). De HAVING geeft daarom
slechts een top-6!
Het probleem van de hoogste totale boetes kan worden opgelost door van de query uit het
begin een view te maken en daarop eenzelfde query als voor de cijfers los te laten.
HOOFDSTUK 10
Opgave 3a
INSERT INTO uitleningen(llnr, exnr, boeknr, datum_uit)
VALUES('83','1','13','2006-03-03')
Opgave 3b
UPDATE leerlingen
SET STRAAT = 'Veldwachterserf', HUISNUMMER = 14, PLAATS = 'Houten', POSTCODE
= '3991KW'
WHERE llnr = 77
Opgave 3c
DELETE FROM reserveringen
WHERE llnr = 78
Opgave 4
CREATE TABLE leden
(
llnr INT NOT NULL AUTO_INCREMENT,
voornaam VARCHAR(15) NOT NULL,
tussenvoegsel VARCHAR(10),
achternaam VARCHAR(20) NOT NULL,
straat VARCHAR(20) NOT NULL,
huisnummer INT NOT NULL,
postcode VARCHAR(6) NOT NULL,
plaats VARCHAR(20) NOT NULL,
telefoon VARCHAR(10),
geslacht VARCHAR(1) NOT NULL,
geb_datum DATE NOT NULL,
klas VARCHAR(2),
PRIMARY KEY(llnr)
);