Joins och relationer
Joins är limmet som binder ihop tabellerna. Utan dem sitter du fast med fragment av information – med dem får du en helhetsbild.
TL;DR
INNER JOIN– matcha rader där båda tabellerna har träff.LEFT JOIN– behåll allt från vänster tabell, även om höger saknar motsvarighet.RIGHT/FULL JOIN– spegelvända varianter (mindre vanliga i vardagen men bra att känna till).- Använd alias (
s,o) för att hålla frågan lättläst.
Varför JOIN?
I relationsdatabaser sparas data i separata tabeller för att undvika upprepning. JOIN låter dig kombinera data från dessa tabeller baserat på relationer mellan dem.
Exempeldata
Vi använder dessa tabeller i alla exempel:
Students:
| StudentId | FirstName | LastName |
|---|---|---|
| 1 | Anna | Svensson |
| 2 | Bengt | Larsson |
| 3 | Cecilia | Nilsson |
| 4 | David | Eriksson |
Enrollments:
| EnrollmentId | StudentId | CourseCode |
|---|---|---|
| 1 | 1 | PRG101 |
| 2 | 1 | MAT101 |
| 3 | 2 | PRG101 |
| 4 | 2 | ENG101 |
| 5 | 3 | MAT101 |
Observera: David (StudentId 4) har inga kurser registrerade.
INNER JOIN – endast matchningar
INNER JOIN returnerar bara de rader där det finns en matchning i båda tabellerna. Detta är den vanligaste typen av JOIN.
SELECT s.StudentId, s.FirstName, e.CourseCode
FROM Students AS s
INNER JOIN Enrollments AS e ON s.StudentId = e.StudentId;
Resultat:
| StudentId | FirstName | CourseCode |
|---|---|---|
| 1 | Anna | PRG101 |
| 1 | Anna | MAT101 |
| 2 | Bengt | PRG101 |
| 2 | Bengt | ENG101 |
| 3 | Cecilia | MAT101 |
Förklaring: Endast studenter som har kurser visas. David saknas eftersom han inte har någon rad i Enrollments. Anna och Bengt får flera rader eftersom de har flera kurser.
LEFT JOIN – behåll allt från vänster
LEFT JOIN returnerar alla rader från vänster tabell (Students), även om det inte finns matchningar i höger tabell (Enrollments). Saknade värden fylls med NULL.
SELECT s.StudentId, s.FirstName, e.CourseCode
FROM Students AS s
LEFT JOIN Enrollments AS e ON s.StudentId = e.StudentId
ORDER BY s.StudentId;
Resultat:
| StudentId | FirstName | CourseCode |
|---|---|---|
| 1 | Anna | PRG101 |
| 1 | Anna | MAT101 |
| 2 | Bengt | PRG101 |
| 2 | Bengt | ENG101 |
| 3 | Cecilia | MAT101 |
| 4 | David | NULL |
Förklaring: Alla studenter visas, inklusive David. Eftersom David inte har några kurser får CourseCode värdet NULL för honom. Detta är användbart för att hitta “saknar”-relationer.
Hitta “saknar”-relationer med LEFT JOIN
En av de kraftfullaste användningarna av LEFT JOIN är att hitta rader som saknar en relation.
-- Hitta studenter som inte har några kurser
SELECT s.StudentId, s.FirstName, s.LastName
FROM Students AS s
LEFT JOIN Enrollments AS e ON s.StudentId = e.StudentId
WHERE e.EnrollmentId IS NULL;
Resultat:
| StudentId | FirstName | LastName |
|---|---|---|
| 4 | David | Eriksson |
Förklaring: LEFT JOIN ger David en rad med NULL i Enrollments-kolumnerna. WHERE-villkoret e.EnrollmentId IS NULL filtrerar fram endast de studenter som saknar enrollments.
RIGHT och FULL JOIN
RIGHT JOIN är spegelvändningen av LEFT JOIN – den behåller alla rader från höger tabell:
-- RIGHT JOIN (stöds inte i SQLite, men fungerar i MySQL/SQL Server)
SELECT s.FirstName, e.CourseCode
FROM Students AS s
RIGHT JOIN Enrollments AS e ON s.StudentId = e.StudentId;
Detta skulle visa alla enrollments, även om det finns orphaned enrollments utan student.
FULL OUTER JOIN (PostgreSQL, SQL Server) behåller rader från båda tabellerna, även om matchning saknas. SQLite stödjer inte detta direkt, men det kan återskapas med UNION.
CROSS JOIN – kartesisk produkt
CROSS JOIN skapar alla möjliga kombinationer mellan två tabeller.
Exempeldata - Courses:
| CourseCode | CourseName |
|---|---|
| PRG101 | Programmering |
| MAT101 | Matematik |
SELECT s.FirstName, c.CourseName
FROM Students AS s
CROSS JOIN Courses AS c
WHERE s.StudentId <= 2; -- Begränsa för läsbarhet
Resultat:
| FirstName | CourseName |
|---|---|
| Anna | Programmering |
| Anna | Matematik |
| Bengt | Programmering |
| Bengt | Matematik |
Förklaring: Varje student kopplas till varje kurs, totalt 2 studenter × 2 kurser = 4 rader. Använd med försiktighet – stora tabeller kan ge enorma resultat!
Self JOIN – jämföra inom samma tabell
Self JOIN används när en tabell refererar till sig själv, till exempel för hierarkier.
Exempeldata - Employees:
| EmployeeId | EmployeeName | MentorId |
|---|---|---|
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Charlie | 1 |
| 4 | Diana | 2 |
SELECT
mentor.EmployeeName AS Mentor,
mentee.EmployeeName AS Mentee
FROM Employees AS mentor
INNER JOIN Employees AS mentee ON mentor.EmployeeId = mentee.MentorId;
Resultat:
| Mentor | Mentee |
|---|---|
| Alice | Bob |
| Alice | Charlie |
| Bob | Diana |
Förklaring: Samma tabell används två gånger med olika alias (mentor, mentee). Vi kopplar mentorer till deras mentees via MentorId.
JOIN med GROUP BY – kraftfulla rapporter
Kombinationen av JOIN och GROUP BY är perfekt för sammanfattningar.
SELECT
s.StudentId,
s.FirstName,
COUNT(e.EnrollmentId) AS CourseCount
FROM Students AS s
LEFT JOIN Enrollments AS e ON s.StudentId = e.StudentId
GROUP BY s.StudentId, s.FirstName
ORDER BY CourseCount DESC;
Resultat:
| StudentId | FirstName | CourseCount |
|---|---|---|
| 1 | Anna | 2 |
| 2 | Bengt | 2 |
| 3 | Cecilia | 1 |
| 4 | David | 0 |
Förklaring: LEFT JOIN säkerställer att alla studenter inkluderas. GROUP BY grupperar per student, och COUNT() räknar deras kurser. David får 0 eftersom han saknar kurser.
Tips & best practices
- Indexera foreign key-kolumnen (
Enrollments.StudentId). - Använd tydliga alias (
Students AS s). - Filtrera i
ONnär du vill påverka joinen, iWHEREnär du vill filtrera efter join. - Undvik
SELECT *i produktion – välj kolumner explicit.
Vanliga fallgropar
- Dubblerade rader: kontrollera att du inte joinar på en 1:N relation utan att använda
DISTINCT/GROUP BYnär du bara vill ha unika. - NULL-problem:
WHERE e.CourseCode IS NOT NULLefter enLEFT JOINtar bort vänster-rader – flytta filtret tillON. - Fel alias: små stavfel i alias leder snabbt till “ambiguous column”-fel.
Sammanfattning
JOIN är fundamentalt för att arbeta med relationsdatabaser:
- INNER JOIN – visa endast matchningar mellan tabeller
- LEFT JOIN – behåll alla från vänster, fyll höger med NULL om saknas
- RIGHT JOIN – behåll alla från höger (omvänd LEFT JOIN)
- CROSS JOIN – alla kombinationer (kartesisk produkt)
- Self JOIN – koppla tabell till sig själv för hierarkier
Kom ihåg:
- Använd tydliga alias (s, e, c) för läsbarhet
- Indexera foreign key-kolumner för prestanda
- LEFT JOIN + WHERE NULL = hitta “saknar”-relationer
- Kombinera med GROUP BY för rapporter
ON vs WHERE vid JOIN:
ON– styr vilka rader som joinasWHERE– filtrerar resultatet efter join
Dad joke
Varför gillar databasen parmiddagar?
För att den får joina två tabeller åt gången.