🔍 SQL

IDATT2002 – NTNU Eksamensforberedelse

⚠️ Eksamen 22. mai 2026 Kode E – ingen hjelpemidler 4 timer 40% ER/Relmod · 40% SQL · 20% Diverse

// SELECT – grunnstruktur

Rekkefølgen på klausulene er fast og må følges:

SELECT kolonne(r) -- hva vil du se? FROM tabell -- hvilken tabell? JOIN ... -- koble inn andre tabeller WHERE betingelse -- filtrer rader (før gruppering) GROUP BY kolonne(r) -- grupper radene HAVING betingelse -- filtrer grupper (etter gruppering) ORDER BY kolonne(r) ASC/DESC -- sorter resultatet
Vanlig feil: WHERE kan ikke bruke aggregatfunksjoner (SUM, COUNT osv.). Bruk HAVING for det. WHERE filtrerer enkeltrad, HAVING filtrerer grupper.

// JOIN

JOIN brukes for å koble data fra flere tabeller basert på en felles kolonne.

INNER JOIN

Returnerer kun rader som har match i begge tabeller.

SELECT a.navn, av.avd_navn FROM ANSATT a INNER JOIN AVDELING av ON a.avd_id = av.avd_id;

LEFT JOIN

Returnerer alle rader fra venstre tabell, med NULL for høyre tabell der det ikke er match. Nyttig for å finne rader uten tilknytning.

-- Finn alle studier, også de uten søkere SELECT ls.studienavn, COUNT(ss.sokernr) AS antall_søkere FROM LÆRERSTED_STUDIUM ls LEFT JOIN SØKER_STUD ss ON ls.studid = ss.studid GROUP BY ls.studid, ls.studienavn;
Huskeregel: Vil du finne rader som IKKE har en kobling? Bruk LEFT JOIN og sjekk WHERE høyretabell.id IS NULL.
-- Studier uten noen søkere SELECT ls.studienavn FROM LÆRERSTED_STUDIUM ls LEFT JOIN SØKER_STUD ss ON ls.studid = ss.studid WHERE ss.studid IS NULL;

// Aggregatfunksjoner

Eksamenrelevant

Disse er de eneste aggregatfunksjonene som er pensum:

  • COUNT(*) – teller alle rader inkl. NULL
  • COUNT(kolonne) – teller rader der kolonnen ikke er NULL
  • SUM(kolonne) – summerer verdier
  • AVG(kolonne) – gjennomsnittsverdi
  • MIN(kolonne) – laveste verdi
  • MAX(kolonne) – høyeste verdi
-- Total inntekt og antall passeringer per stasjon -- men kun stasjoner med over 100 passeringer SELECT stasjon_id, COUNT(*) AS antall_passeringer, SUM(belop) AS total_inntekt FROM PASSERING GROUP BY stasjon_id HAVING COUNT(*) > 100 ORDER BY total_inntekt DESC;

// Subqueries

En subquery er en SELECT inni en annen SELECT. Brukes typisk med IN eller NOT IN.

IN – finne rader med kobling

-- Studenter som har søkt på minst ett studie SELECT navn FROM STUDENT WHERE student_id IN (SELECT student_id FROM SØKNAD);

NOT IN – finne rader uten kobling

-- Studier ingen har søkt på SELECT studienavn FROM LÆRERSTED_STUDIUM WHERE studid NOT IN (SELECT studid FROM SØKER_STUD);
Obs: NOT IN med NULL-verdier kan gi uventede resultater. Hvis subqueryens kolonne kan inneholde NULL, bruk LEFT JOIN ... WHERE IS NULL i stedet.

// CREATE VIEW

Eksamenrelevant

En VIEW er en lagret SELECT-spørring som oppfører seg som en virtuell tabell. Den lagrer ingen data – spørringen kjøres på nytt hver gang du bruker viewen.

-- Opprett en view CREATE VIEW AKTIVE_BOMSTASJONER AS SELECT stasjon_id, navn, type FROM BOMSTASJON WHERE operativ_til IS NULL; -- Bruk viewen akkurat som en tabell SELECT * FROM AKTIVE_BOMSTASJONER; -- Bruk viewen i en JOIN SELECT ab.navn, COUNT(p.pas_id) AS antall FROM AKTIVE_BOMSTASJONER ab JOIN PASSERING p ON ab.stasjon_id = p.stasjon_id GROUP BY ab.stasjon_id;

Fordeler med VIEW: forenkler komplekse spørringer, kan brukes til tilgangskontroll (gi brukere tilgang til view, ikke rå tabeller).

// DISTINCT og NULL

-- Hent unike kjøretøytyper (ingen duplikater) SELECT DISTINCT kjøretøytype FROM KJØRETØY; -- NULL-sjekk – bruk IS NULL / IS NOT NULL, aldri = NULL SELECT * FROM ANSATT WHERE avd_id IS NULL; SELECT * FROM ANSATT WHERE avd_id IS NOT NULL;

// Eksempel fra eksamen v25 – Blomster

Fra tidligere eksamen

Gitt tabellene:

BLOMST(blomst_id, navn, farge, pris) ORDRE(ordre_id, dato, kunde_id*) ORDRELINJE(ordre_id*, blomst_id*, antall)
-- Total omsetning per blomst, kun blomster solgt mer enn 10 ganger SELECT b.navn, SUM(ol.antall * b.pris) AS omsetning FROM BLOMST b INNER JOIN ORDRELINJE ol ON b.blomst_id = ol.blomst_id GROUP BY b.blomst_id, b.navn HAVING SUM(ol.antall) > 10 ORDER BY omsetning DESC;
-- Blomster som aldri har blitt bestilt SELECT navn FROM BLOMST WHERE blomst_id NOT IN (SELECT blomst_id FROM ORDRELINJE);
🎯 Øv på SQL-spørsmål i quizen →