ER- och EER-diagram kan ritas på flera olika sätt. Om du använder en annan notation än kursboken, måste du förklara den notation som du använder.
a) Visa en tydlig översikt över dina tabeller. Ange vilka relationer som finns och vilka attribut varje relation innehåller, med väl valda exempeldata. Ange också alla kandidatnycklar, vilken av dessa som är primärnyckel, samt vilka referensattribut som finns och vad de refererar till.
Personer(Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet)
Platser(Nummer, Namn, Gatuadress, Ort)
Vaccinationer(ID, Datum, Person, Plats)
Gruppvaccinationer(ID, Datum, Plats)
Gruppvaccinerade(Gruppvaccination, Person)Kandidatnycklar är understrukna. I de tabeller där det finns flera kandidatnycklar är den första primärnyckel.
Främmande nycklar:
Vaccinationer.Person till Personer.Personnummer
Vaccinationer.Plats till Platser.Nummer
Gruppvaccinationer.Plats till Platser.Nummer
Gruppvaccinerade.Gruppvaccination tlll Gruppvaccinationer.ID
Gruppvaccinerade.Person till Personer.PersonnummerTabellerna med exempeldata:
Personer Personnummer Namn Gatuadress Ort Ålder Prioritet Vikt 450222-1122 Anna Alm Vägen 5 Örebro 75 2 100 551112-9917 Bengt Berg Vägen 6 Örebro 65 0 100 650402-7266 Cecilia Ceder Vägen 7 Örebro 55 null 70 720515-4599 Don Duck Vägen 8 Örebro 48 0 100 871031-1914 Erik Ek Vägen 9 Örebro 33 2 200
Platser Nummer Namn Gatuadress Ort 1 Örebro COVID-camp USÖ Örebro 2 Kumla COVID-camp Vägen 1 Kumla
Vaccinationer ID Datum Person Plats 1 2021-01-13 450222-1122 1 2 2021-01-13 551112-9917 1 3 2021-01-13 720515-4599 2
Gruppvaccinationer ID Datum Plats 1 2021-01-13 1 2 2021-01-13 1
Gruppvaccinerade Gruppvaccination Person 1 450222-1122 1 551112-9917 2 551112-9917 2 720515-4599
Några kommentarer:
b) I delfrågan ovan står det att man ska ange vilka relationer som finns. Vad är en relation?
En relation i en relationsdatabas är samma sak som en tabell. Det är inte kopplingarna mellan tabellerna som är relationerna.
c) Skriv de SQL-kommandon som behövs för att skapa tabellerna, med lämpliga integritetsvillkor.
CREATE TABLE Personer (Personnummer CHAR(11) NOT NULL PRIMARY KEY, Namn VARCHAR(15), Gatuadress VARCHAR(10), Ort VARCHAR(10), Ålder INTEGER, Prioritet INTEGER, Vikt INTEGER); CREATE TABLE Platser (Nummer INTEGER NOT NULL PRIMARY KEY, Namn VARCHAR(20) NOT NULL UNIQUE, Gatuadress VARCHAR(10), Ort VARCHAR(10)); CREATE TABLE Vaccinationer (ID INTEGER NOT NULL PRIMARY KEY, Datum DATE, Person CHAR(11) REFERENCES Personer(Personnummer), Plats INTEGER REFERENCES Platser(Nummer)); CREATE TABLE Gruppvaccinationer (ID INTEGER NOT NULL PRIMARY KEY, Datum DATE, Plats INTEGER REFERENCES Platser(Nummer)); CREATE TABLE Gruppvaccinerade (Gruppvaccination INTEGER NOT NULL REFERENCES Gruppvaccinationer(ID), Person CHAR(11) REFERENCES Personer(Personnummer), PRIMARY KEY (Gruppvaccination, Person));
För att underlätta provkörningar visas också INSERT-kommandon med exempeldata:
INSERT INTO Personer (Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet) VALUES ('450222-1122', 'Anna Alm', 'Vägen 5', 'Örebro', 75, 100, 0); INSERT INTO Personer (Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet) VALUES ('551112-9917', 'Bengt Berg', 'Vägen 6', 'Örebro', 65, 100, 0); INSERT INTO Personer (Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet) VALUES ('720515-4599', 'Don Duck', 'Vägen 8', 'Örebro', 48, 100, 0); INSERT INTO Personer (Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet) VALUES ('871031-1914', 'Erik Ek', 'Vägen 9', 'Örebro', 33, 200, 0); INSERT INTO Platser (Nummer, Namn, Gatuadress, Ort) VALUES (1, 'Örebro COVID-camp', 'USÖ', 'Örebro'); INSERT INTO Platser (Nummer, Namn, Gatuadress, Ort) VALUES (2, 'Kumla COVID-camp', 'Vägen 1', 'Kumla'); INSERT INTO Vaccinationer (ID, Datum, Person, Plats) VALUES (1, DATE '2021-01-13', '450222-1122', 1); INSERT INTO Vaccinationer (ID, Datum, Person, Plats) VALUES (2, DATE '2021-01-13', '551112-9917', 1); INSERT INTO Vaccinationer (ID, Datum, Person, Plats) VALUES (3, DATE '2021-01-13', '720515-4599', 2); INSERT INTO Gruppvaccinationer (ID, Datum, Plats) VALUES (1, DATE '2021-01-13', 1); INSERT INTO Gruppvaccinationer (ID, Datum, Plats) VALUES (2, DATE '2021-01-13', 1); INSERT INTO Gruppvaccinerade (Gruppvaccination, Person) VALUES (1, '450222-1122'); INSERT INTO Gruppvaccinerade (Gruppvaccination, Person) VALUES (1, '551112-9917'); INSERT INTO Gruppvaccinerade (Gruppvaccination, Person) VALUES (2, '551112-9917'); INSERT INTO Gruppvaccinerade (Gruppvaccination, Person) VALUES (2, '720515-4599');
a) (2p) Personen Anna Alm har vaccinerat sig, med en vanlig vaccination (inte en gruppvaccination). Var? Ange adressen till vaccinationsplatsen.
-- Några olika alternativ: SELECT Platser.Gatuadress, Platser.Ort FROM Personer, Vaccinationer, Platser WHERE Personer.Personnummer = Vaccinationer.Person AND Vaccinationer.Plats = Platser.Nummer AND Personer.Namn = 'Anna Alm'; SELECT Platser.Gatuadress, Platser.Ort FROM Personer JOIN Vaccinationer ON Personer.Personnummer = Vaccinationer.Person JOIN Platser ON Vaccinationer.Plats = Platser.Nummer WHERE Personer.Namn = 'Anna Alm'; SELECT Gatuadress, Ort FROM Platser WHERE Nummer IN (SELECT Plats FROM Vaccinationer WHERE Person IN (SELECT Personnummer FROM Personer WHERE Namn = 'Anna Alm'));
b) (2p) Personen Bengt Berg har vaccinerat sig med en gruppvaccination. Vad heter de andra personer som vaccinerades vid samma tillfälle?
SELECT Andra.Namn FROM Personer AS Bengt, Gruppvaccinerade AS Bengts, Gruppvaccinerade AS Andras, Personer AS Andra WHERE Bengt.Personnummer = Bengts.Person AND Bengts.Gruppvaccination = Andras.Gruppvaccination AND Andras.Person = Andra.Personnummer AND Bengt.Namn = 'Bengt Berg' AND Andra.Personnummer != Bengt.Personnummer; -- Den här frågan ger även Bengt Bergs namn: SELECT Namn FROM Personer WHERE Personnummer IN (SELECT Person FROM Gruppvaccinerade WHERE Gruppvaccination IN (SELECT Gruppvaccination FROM Gruppvaccinerade WHERE Person IN (SELECT Personnummer FROM Personer WHERE Namn = 'Bengt Berg')));
c) (2p) Hur många personer har vaccinerats med gruppvaccinationer?
SELECT COUNT(*) FROM Gruppvaccinerade; -- Eller om man bara vill räkna unika personer, -- dvs om samma person gruppvaccineras två gånger så räknas det bara som en person: SELECT COUNT(DISTINCT Person) FROM Gruppvaccinerade;
d) (3p) Vad heter den person som har högst prioritet, av de som ännu inte är vaccinerade (vare sig med en vanlig vaccination eller en gruppvaccination)?
-- Med en CTE: WITH Ovaccinerade AS (SELECT Namn, Prioritet FROM Personer WHERE Personnummer NOT IN (SELECT Person FROM Vaccinationer) AND Personnummer NOT IN (SELECT Person FROM Gruppvaccinerade)) SELECT Namn FROM Ovaccinerade WHERE Prioritet = (SELECT MAX(Prioritet) FROM Ovaccinerade); -- Med en vy: CREATE VIEW Ovaccinerade AS SELECT Namn, Prioritet FROM Personer WHERE Personnummer NOT IN (SELECT Person FROM Vaccinationer) AND Personnummer NOT IN (SELECT Person FROM Gruppvaccinerade); SELECT Namn FROM Ovaccinerade WHERE Prioritet = (SELECT MAX(Prioritet) FROM Ovaccinerade); -- Med Mimer-syntax: SELECT Namn FROM Personer WHERE Personnummer NOT IN (SELECT Person FROM Vaccinationer) AND Personnummer NOT IN (SELECT Person FROM Gruppvaccinerade) ORDER BY Prioritet DESC FETCH FIRST 1; -- Även MySQLs syntax med "LIMIT" och SQL Servers syntax med "TOP" är godkända.
a) Lägg in personen Cecilia Ceder, med personnummer 650402-7266, adressen Vägen 7, Örebro, ålder 55 år och vikt 70 kilo.
INSERT INTO Personer (Personnummer, Namn, Gatuadress, Ort, Ålder, Vikt, Prioritet) VALUES ('650402-7266', 'Cecilia Ceder', 'Vägen 7', 'Örebro', 55, 70, NULL);
b) Riskgrupper ska vaccineras först. Låt alla personer som är 70 år eller äldre, och alla personer som väger mer än 130 kilo, få prioriteten 2.
UPDATE Personer SET Prioritet = 2 WHERE Ålder >= 70 OR Vikt > 130;
c) Det visar sig att vaccinet som levererades till vaccinationsplatsen Örebro COVID-camp var verkningslöst. Endast vanliga vaccinationer genomfördes där, inga gruppvaccinationer. Ta bort alla vaccinationer som gjordes på den vaccinationsplatsen.
DELETE FROM Vaccinationer WHERE Plats IN (SELECT Nummer FROM Platser WHERE Namn = 'Örebro COVID-camp');
a) Vilka index bör man skapa för att få den sökningen att gå snabbare? Skriv CREATE INDEX-kommandon.
CREATE INDEX PersonensPersonnummer ON Personer(Personnummer); CREATE INDEX VaccineradPerson ON Vaccinationer(Person); CREATE INDEX Vaccinationsplats ON Vaccinationer(Plats); CREATE INDEX Platsnummer ON Platser(Nummer); CREATE INDEX Personnamn ON Personer(Namn);
b) Ange ett index som inte skulle gjort att sökningen går snabbare, och förklara varför det indexet inte hjälper.
-- Några förslag: CREATE INDEX DåligtIndex1 ON Gruppvaccinationer(ID); -- Tabellen Gruppvaccinationer är inte med alls i frågan. CREATE INDEX DåligtIndex2 ON Vaccinationer(Datum); -- Kulumnen Datum i tabellen Vaccinationer är inte med alls i frågan. CREATE INDEX DåligtIndex3 ON Platser(Gatuadress); -- Kulumnen Gatuadress i tabellen Platser är med i svaret från -- sökningen, men används inte för att hitta data. CREATE INDEX DåligtIndex4 ON Vaccinationer(ID, Datum, Person, Plats); -- Ett sammansatt index kan bara användas för sökning på ett prefix av -- de indexerade kolumnerna, alltså ID, ID+Datum, ID+Datum+Person eller -- alla fyra kolumnerna ID+Datum+Person+Plats. Eftersom kolumnen ID -- inte är med alls i frågan, kan det här indexet inte användas vid -- körningen av frågan. CREATE INDEX DåligtIndex5 ON Personer(Prioritet); -- Vi kan gissa från uppgifterna ovan att det blir ganska få olika värden -- på prioriteterna, kanske bara värdena 0, 1 och 2. Ett index på prioritet -- skulle i så fall ge mycket dålig selektivitet. En sökning på en viss -- prioritet kommer att ge väldigt många rader som svar, och i så fall är -- det förmodligen snabbare att bara läsa igenom tabellen sekventiellt. -- Och dessutom används ju inte den här kolumnen i frågan.
Visa med tydliga exempel från databasen som du skapat i uppgifterna ovan vad som skulle kunna hända som gör att var och en av dessa egenskaper bryts, om man inte använder transaktioner.