IN2090-ukesoppgaver: Uke 1
Motivasjon for Databaser og Datamodellering
Oppgavene denne første uken handler ikke direkte om pensum, men gir en motivasjon til hvorfor det vi skal gjennomgå i kurset er nyttig og nødvendig.
De første tre oppgavene bruker tre CSV-filer. CSV er et enkelt format for å lagre data på tabell-form. I en CSV fil inneholder første linje en komma-separert liste med kolonne-navn, mens de etterfølgende linjene representerer radene i tabellen hvor hver kolonnes verdi er separert med komma.
Innholdet i de tre filene som oppgavene under bruker er gitt under:
studenter.csv
:
studeintid, fornavn, etternavn, født
1, kari, borg, 1993-02-23
2, per, nes, 1996-07-08
3, mina, gran, 1990-11-03
4, carl, smith, 1992-09-05
tar_kurs.csv
:
studentid, kurskode, karakter
1, IN2090, B
1, IN2020, C
2, IN2000, C
3, MAT2250, A
1, AST1010, D
4, FYS2000, C
2, BIOS3010, A
4, IN3000, C
2, INF4000, B
3, MAT1100, E
kurs.csv
:
kurskode, navn, studiepoeng
AST1010, Astronomi - en kosmisk reise, 10
MAT2250, Diskret matematikk, 10
IN2000, Software Engineering med prosjektarbeid, 20
BIOS3010, Bioinformatikk, 10
IN1010, Objektorientert programmering, 10
MAT1100, Kalkulus, 10
IN2090, Databaser og datamodellering, 10
BIOS3300, Marinbiologi, 10
IN5360, Forskerlinjen II, 15
MAT1100, Kalkulus, 10
IN1150, Logiske metoder, 10
IN3000, Operativsystemer, 20
Den første filen (studenter.csv
) inneholder altså informasjon om studenter, deres (unike) student-id, fornavn, etternavn og datoen de er født. Den andre filen (tar_kurs.csv
) sier hvilke kurs ulike studenter har tatt (og referer til studenter med deres student-id og kurs med deres kurskode), samt karakteren studenten fikk i kurset. Den siste filen (kurs.csv
) inneholder informasjon om kurs, kursets (unike) kurs-kode, navn og antall studiepoeng.
Så f.eks. for å finne navnet til alle kursene som kari
tar, må vi først finne hennes studentid
i studenter.csv
-filen, så finne kurskodene hun tar i tar_kurs.csv
, og så til slutt slå opp navnene på disse kursene i kurs.csv
.
1. Finn studenter
Skriv psudokode (alternativt Python- eller Java-kode om du ønsker) for et program som lister opp navn (fornavn og etternavn) på alle studenter som har et etternavn som starter på 'g'
.
Du kan anta at du har en funksjon read_csv
som tar en streng som inneholder filnavnet til en CSV-fil, leser filen og returnerer en liste med tupler som inneholder dataene i filen. Du kan hente ut verdier fra tuplene som om de var arrays (hvor indeksene starter på 1
), f.eks. vil t[1]
gi ut det første elementet i tupplet t
.
Ellers kan du bruke vanlige for
- og while
-løkker, if
-tester, osv.
Løsningsforslag:
:= csv_read('student.csv')
students
for s in students:
if s[3].startsWith('g'):
print(s[2] + " " + s[3])
end if
end for
2. Finn kurs
Skriv et program (pseudokode, Python- eller Java-kode) som lister opp kurskode og navn på alle kurs med en kurskode som starter med "IN"
, som er tatt av studenter som er født etter 1. januar 1992. Sorter listen alfabetisk på kurskode, og bare skriv ut hvert kurs én gang.
Du kan gjøre de samme antagelsene her som i forrige oppgave. Du kan også anta at datoer kan sammenlikned med <
, f.eks. vil "1992-01-01" < "1993-04-05"
.
Løsningsforslag:
:= csv_read('student.csv')
studenter := csv_read('courses.csv')
kurs := csv_read('takes_course.csv')
tar_kurs
= new Sorted_list()
sorterte_kurs
for s in studenter:
if ("1992-01-01" < s[4]):
for tk in tar_kurs:
if s[1] = tk[1] and tk[1].starts_with("IN"):
for k in kurs:
if tk[2] = k[1] and not sorterte_kurs.contains(k):
.add(k)
sorterte_kursend if
end for
end if
end for
end if
end for
for k in sorterte_kurs:
print(k[1] + " " + k[2])
end for
3. Lag rapport
Skriv et program (pseudokode, Python- eller Java-kode) som lager en ny CSV-fil studenter_per_kurs.csv
som inneholder antall studenter som har tatt hvert kurs og fødselsdatoen på den yngste personen som har tatt kurset. Filen skal inneholde kurskode, navnet på kurset, antall studiepoeng, antall studenter som har tatt kurset og fødselsdatoen til den yngste som har tatt kurset. Dersom et kurs aldri er tatt skal det likevel listes opp med antall lik 0
og den tomme strengen som dato (""
).
Du kan anta at du kan skrive en liste med tupler til en CSV-fil med funksjonen csv_write(tupler, kolonner, filnavn)
hvor tupler
er listen med tupler du ønsker å skrive, kolonner
er en liste med kolonne navn (som skal skrives øverst i filen), og filnavn
er navnet på filen dataene skal skrives til.
Løsningsforslag:
:= csv_read('student.csv')
studenter := csv_read('courses.csv')
kurs := csv_read('takes_course.csv')
tar_kurs
= new List()
ant_per_kurs
for k in kurs:
:= 0
ant := ""
yngst for tk in tar_kurs:
if k[1] = tk[1]:
= ant + 1
ant for s in studenter:
if tk[2] = s[1] and (yngst == "" or s[3] < yngst):
:= s[3]
yngst end if
end for
end if
end for
.add(new Tuple(k[1], k[2], k[3], ant, yngst))
ant_per_kursend for
(ant_per_kurs, ["Kurskode", "Navn", "Studiepoeng", "Antall_studenter", "Yngste_student"]); csv_write
4. Strukturere Data
Vi ønsker nå å lagre informasjon om resultatene fra en sjakk-turnering. Lag derfor CSV-filer som inneholder følgende informasjon:
- Kari Olesen, med deltakernummer 43 og nasjonalitet Norge, vant i partinummer 1 som hvit spiller over Clark Smith (som har deltakernummer 12 og nasjonalitet UK)
- Clark Smith, med deltakernummer 12 og nasjonalitet UK, vant i partinummer 3 som sort spiller over Laura Fritz (som har deltakernummer 7 og nasjonalitet Tyskland)
- Kari Olesen, med deltakernummer 43 og nasjonalitet Norge, spilte i partinummer 2 som sort spiller over Laura Fritz (som har deltakernummer 7 og nasjonalitet Tyskland), og spillet endte i remi (altså uavgjort)
Løsningsforslag
spillere.csv
:
deltakernummer, navn, nasjonalitet
43, Kari Olesen, Norge
12, Clark Smith, UK
7, Laura Fritz, Tyskland
partier.csv
:
partinummer, hvit, sort, vinner
1, 43, 12, hvit
3, 7, 12, sort
2, 7, 43, remi
Nytten av Databaser og Datamodellering
Disse oppgavene er ment å vise at for å jobbe med data kreves det mer enn bare vanlige programmeringsspråk og filer. Dette gjelder spesielt når mengden data blir store og kompliserte.
Man trenger da spesielle teknologier som kan håndtere store og kompliserte datamengder. Programmene du skrev over laster all data inn i minne. Data benyttet av en vanlig bedrift eller organisasjon kommer fort opp i gigabyte eller terrabyte, altså mer enn en vanlig datamaskin har av minne.
I tillegg trengs enklere språk for å formulere spørringer. Kompleksiteten til spørringene vokser gjerne med kompleksiteten til dataene, og det vil etterhvert bli umulig å formulere spørringer ved hjelp av for
-løkker og if
-tester. Da trengs et eget skreddersydd språk for dette, slik som SQL, som vi skal lære i dette kurset.
F.eks. kan oppgave 1. over løses i SQL med følgende spørring:
SELECT fornavn, etternavn
FROM studenter
WHERE etternavn LIKE 'g%';
og oppgave 2. kan løses med
SELECT DISTINCT c.kurskode, c.navn
FROM studenter AS s
JOIN tar_kurs AS tk ON s.id = c.student
JOIN kurs AS k ON tc.kurs = k.kurskode
WHERE '1992-01-01' < s.født AND c.kurskode LIKE 'IN%'
ORDER BY c.kurskode;
mens oppgave 3 kan løses med
CREATE TABLE studenter_per_kurs(
int,
kurskode text, navn text, studiepoeng int, yngste_student date
antall_studenter AS
) SELECT k.kurskode, k.navn, k.studiepoeng, count(s.id), min(s.født)
FROM kurs AS k
LEFT JOIN tar_kurs USING (kurskode)
LEFT JOIN student AS s USING (studentid)
GROUP BY k.kurskode, k.navn, k.studiepoeng;
Disse spørringene er ikke bare enklere, men også langt mer effektive på uthenting og prosessering av dataene. De skalerer også til millioner av studenter og kurs, siden all data aldri trengs å lastes inn i minne på en gang.
I tillegg gir databasesystemer bedre og mer tilpassede sikkerhets mekanismer for dataene, støtter kompliserte datatyper og avanserte data strukturer.
Før man kan lagre data må man bestemme seg for en struktur på dataene, slik vi gjorde i den siste oppgaven over. Hvilken struktur vi velger for dataene har mye å si både for hvor enkelt og effektivt dataene kan brukes og vedlikeholdes. Data-modellering er en prosess som lar oss finne god struktur på dataene og er også en sentral del av kurset.