← Tilbage til DataLex.dk
SQL

SQL Joins

Forstå alle join-typer i SQL med konkrete eksempler. Fra INNER JOIN til FULL OUTER JOIN – lær hvornår du bruger hvilken type.

Hvad er en SQL Join?

En JOIN i SQL kombinerer rækker fra to eller flere tabeller baseret på en relateret kolonne. Det er fundamentet for at arbejde med normaliserede databaser, hvor data er fordelt på flere tabeller for at undgå redundans.

Uden joins ville du skulle køre separate forespørgsler mod hver tabel og manuelt kombinere resultaterne i din applikation. Med joins håndterer databasen sammenkoblingen, hvilket er langt mere effektivt og giver databasens query optimizer mulighed for at vælge den bedste execution plan.

SQL definerer flere join-typer, og valget af den rigtige type afgør hvilke rækker der inkluderes i resultatet. De fire primære typer er INNER JOIN, LEFT JOIN, RIGHT JOIN og FULL OUTER JOIN.

De fire primære join-typer

JOIN

INNER JOIN

Returnerer kun rækker der har match i begge tabeller. Den mest brugte join-type.

SELECT * FROM orders
INNER JOIN customers
ON orders.customer_id = customers.id;

Hvornår: Når du kun vil se data der findes i begge tabeller – f.eks. ordrer med tilhørende kundedata.

JOIN

LEFT JOIN

Returnerer alle rækker fra venstre tabel, og matchende rækker fra højre. NULL hvor der ikke er match.

SELECT * FROM customers
LEFT JOIN orders
ON customers.id = orders.customer_id;

Hvornår: Når du vil se alle kunder – også dem uden ordrer. Viser NULL i ordre-kolonnerne for kunder uden køb.

JOIN

RIGHT JOIN

Returnerer alle rækker fra højre tabel, og matchende rækker fra venstre. Spejlbillede af LEFT JOIN.

SELECT * FROM orders
RIGHT JOIN products
ON orders.product_id = products.id;

Hvornår: Når du vil se alle produkter – også dem der aldrig er bestilt. Mindre brugt end LEFT JOIN.

JOIN

FULL OUTER JOIN

Returnerer alle rækker fra begge tabeller. NULL hvor der ikke er match i den modsatte tabel.

SELECT * FROM employees
FULL OUTER JOIN departments
ON employees.dept_id = departments.id;

Hvornår: Når du vil have et komplet overblik – f.eks. alle medarbejdere OG alle afdelinger, uanset om de matcher.

CROSS JOIN og SELF JOIN

CROSS JOIN

Producerer det kartesiske produkt af to tabeller – altså alle mulige kombinationer af rækker. Har du 10 kunder og 5 produkter, giver CROSS JOIN 50 rækker.

SELECT * FROM sizes
CROSS JOIN colors;

Bruges sjældent, men nyttigt til at generere alle kombinationer – f.eks. størrelser x farver i en webshop.

SELF JOIN

Joiner en tabel med sig selv. Bruges når rækker i samme tabel har en relation til hinanden – f.eks. medarbejdere og deres chefer.

SELECT e.name, m.name AS manager
FROM employees e
LEFT JOIN employees m
ON e.manager_id = m.id;

Kræver aliaser for at skelne mellem de to "kopier" af tabellen.

Praktisk eksempel: Webshop-database

Forestil dig en simpel webshop med tre tabeller: customers, orders og products. Her er typiske joins du ville bruge:

// Alle ordrer med kundenavn og produktnavn

SELECT
  customers.name AS kunde,
  products.name AS produkt,
  orders.quantity AS antal,
  orders.created_at AS dato
FROM orders
INNER JOIN customers ON orders.customer_id = customers.id
INNER JOIN products ON orders.product_id = products.id
ORDER BY orders.created_at DESC;

// Kunder der aldrig har bestilt noget

SELECT customers.name, customers.email
FROM customers
LEFT JOIN orders ON customers.id = orders.customer_id
WHERE orders.id IS NULL;

// Antal ordrer per kunde (inkl. kunder med 0 ordrer)

SELECT
  customers.name,
  COUNT(orders.id) AS antal_ordrer
FROM customers
LEFT JOIN orders ON customers.id = orders.customer_id
GROUP BY customers.id, customers.name
ORDER BY antal_ordrer DESC;

Performance og indeksering

Joins kan være dyre operationer, især på store tabeller. Den vigtigste optimering er at sikre at kolonnerne i JOIN-betingelsen er indekseret. Uden indeks skal databasen scanne hele tabellen for hvert match.

Indekser join-kolonner

Foreign keys og kolonnerne i ON-betingelsen bør altid have et indeks. Det reducerer join-operationen fra O(n*m) til O(n*log m).

Begræns resultatsættet

Brug WHERE-betingelser til at filtrere tidligt. Jo færre rækker databasen skal joine, jo hurtigere kører forespørgslen.

Vælg kun nødvendige kolonner

SELECT * er fristende men ineffektivt. Angiv kun de kolonner du faktisk bruger – det reducerer I/O og memory.

Brug EXPLAIN

Kør EXPLAIN foran din forespørgsel for at se execution plan. Tjek at databasen bruger indekser og ikke laver full table scans.

Joins i forskellige databasesystemer

SQL joins fungerer ens på tværs af de fleste relationelle databaser, men der er vigtige nuancer:

-MySQL: Understøtter ikke FULL OUTER JOIN direkte. Du skal kombinere LEFT JOIN og RIGHT JOIN med UNION.
-PostgreSQL: Fuld support for alle join-typer inkl. LATERAL joins, som lader dig referere til kolonner fra den ydre forespørgsel.
-SQLite: Understøtter ikke RIGHT JOIN og FULL OUTER JOIN. Brug LEFT JOIN og vend tabel-rækkefølgen.
-MariaDB: Samme begrænsninger som MySQL. Følger MySQL-syntaksen tæt.

Typiske fejl med SQL Joins

Manglende ON-betingelse

En JOIN uden ON-betingelse bliver til en CROSS JOIN og producerer kartesisk produkt. Med to tabeller af 1.000 rækker giver det 1.000.000 rækker. Tjek altid at din ON-klausul er korrekt.

Forkert join-type

INNER JOIN dropper rækker uden match. Hvis du uventet mangler data i resultatet, overvej om du burde bruge LEFT JOIN i stedet.

Duplikerede rækker

Hvis join-betingelsen matcher flere rækker i den ene tabel, multipliceres rækkerne fra den anden tabel. Brug DISTINCT eller GROUP BY hvis du får uventede dubletter.

NULL-sammenligninger

NULL = NULL giver FALSE i SQL. Joins matcher aldrig på NULL-værdier. Brug IS NULL i WHERE for at finde rækker uden match, eller COALESCE for at håndtere NULL-værdier.

Hurtig reference: Hvornår bruger du hvilken join?

INNER JOINDu vil kun have rækker der matcher i begge tabeller
LEFT JOINDu vil have ALLE rækker fra venstre tabel, uanset om de matcher
RIGHT JOINDu vil have ALLE rækker fra højre tabel (sjældent brugt – vend tabellerne og brug LEFT JOIN)
FULL OUTER JOINDu vil have ALLE rækker fra begge tabeller, med NULL hvor de ikke matcher
CROSS JOINDu vil have alle kombinationer af rækker fra to tabeller
SELF JOINDu skal relatere rækker inden for samme tabel (f.eks. hierarkier)

Relaterede emner