SQL Academy · leksjon

Gå gjennom et kategoritre

Utvid foreldre-barn-trær fullstendig.

Leksjon 2 av 413 trinn

Gå gjennom et kategoritre er en gratis leksjon i SQL Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i SQL Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva er et kategoritre?

Mange virkelige datasett har en forelder-barn-relasjon. En produktkatalog kan ha kategorier som Elektronikk → Telefoner → Smarttelefoner. Hver node har en forelder, slik at det dannes en trestruktur.

I SQL lagres dette vanligvis som en tabell som refererer til seg selv: hver rad har en id og en parent_id som peker på en annen rad i samme tabell.

CREATE TABLE categories (
  id       INT PRIMARY KEY,
  name     VARCHAR(100) NOT NULL,
  parent_id INT REFERENCES categories(id)
);

Eksempeldata for kategorier

La oss fylle ut et lite kategoritre. Rotnoden har parent_id = NULL fordi den ikke har noen forelder. Alle andre noder peker på forelderen sin med en parent_id som ikke er null.

INSERT INTO categories (id, name, parent_id) VALUES
  (1, 'Electronics',   NULL),
  (2, 'Phones',         1),
  (3, 'Laptops',        1),
  (4, 'Smartphones',    2),
  (5, 'Feature Phones', 2),
  (6, 'Gaming Laptops', 3),
  (7, 'Ultrabooks',     3);

Problemet med enkle spørringer

En vanlig SELECT kan bare hente ett nivå om gangen. For å nå tre nivåer ned måtte De ha brukt tre separate spørringer eller tre self joins, noe som blir uhåndterlig etter hvert som treet vokser.

WITH RECURSIVE løser dette ved at en spørring kan referere til sitt eget resultat og gå gjennom nivåene ett etter ett til det ikke finnes flere nye rader.

-- This only shows direct children of Electronics (level 1)
SELECT id, name
FROM   categories
WHERE  parent_id = 1;

Anatomien i WITH RECURSIVE

En rekursiv CTE har to deler, atskilt av UNION ALL:

1. Ankerdel — en vanlig SELECT som leverer startradene.

2. Rekursiv del — en SELECT som kobler CTE-en tilbake til seg selv og produserer neste nivå ved hver iterasjon.

Motoren gjentar den rekursive delen til den returnerer null rader.

WITH RECURSIVE cte AS (
  -- Anchor: starting rows
  SELECT ...
  UNION ALL
  -- Recursive: join cte to base table
  SELECT ... FROM base_table JOIN cte ON ...
)
SELECT * FROM cte;

Gå gjennom hele treet fra roten

Start ved roten (der parent_id IS NULL) og gå nedover til alle etterkommerne. Den rekursive delen kobler hver oppsamlede rad tilbake til categories via foreldre–barn-relasjonen.

WITH RECURSIVE category_tree AS (
  -- Anchor: root nodes
  SELECT id, name, parent_id, 1 AS depth
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  -- Recursive: children of current level
  SELECT c.id, c.name, c.parent_id, ct.depth + 1
  FROM   categories      c
  JOIN   category_tree   ct ON ct.id = c.parent_id
)
SELECT id, name, depth
FROM   category_tree
ORDER  BY depth, id;

Spore stien

Det er nyttig å registrere hele stien fra roten til hver node. Vi kan bygge en path-streng ved å sette sammen navnene på forfedrene etter hvert som vi går dypere i rekursjonen.

Dette gjør det enkelt å vise brødsmulestier som Electronics / Phones / Smartphones.

WITH RECURSIVE category_tree AS (
  SELECT id, name, parent_id,
         name AS path
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  SELECT c.id, c.name, c.parent_id,
         ct.path || ' / ' || c.name
  FROM   categories    c
  JOIN   category_tree ct ON ct.id = c.parent_id
)
SELECT id, name, path
FROM   category_tree
ORDER  BY path;

Starte fra en bestemt node

Du trenger ikke å starte ved roten. Ved å endre ankerdelens WHERE-betingelse kan du gå gjennom deltreet til en hvilken som helst node. Her starter vi fra Phones (id = 2) og henter alle etterkommerne.

WITH RECURSIVE subtree AS (
  SELECT id, name, parent_id, 0 AS depth
  FROM   categories
  WHERE  id = 2          -- start at Phones

  UNION ALL

  SELECT c.id, c.name, c.parent_id, s.depth + 1
  FROM   categories c
  JOIN   subtree    s ON s.id = c.parent_id
)
SELECT id, name, depth
FROM   subtree
ORDER  BY depth, id;

Gå oppover: Finn alle forfedre

Treet kan også traverseres i motsatt retning — oppover fra et blad til roten. Snu ganske enkelt koblingen slik at du følger parent_id oppover i stedet for nedover. Dette er nyttig når du trenger hele brødsmulestien for en kjent bladnode.

WITH RECURSIVE ancestors AS (
  SELECT id, name, parent_id
  FROM   categories
  WHERE  id = 4          -- start at Smartphones

  UNION ALL

  SELECT c.id, c.name, c.parent_id
  FROM   categories c
  JOIN   ancestors  a ON a.parent_id = c.id
)
SELECT id, name
FROM   ancestors
ORDER  BY id;

Legge til en innrykket visning

Et vanlig UI-mønster er å vise barnenoder med visuelt innrykk. Vi kan bruke REPEAT (eller LPAD) sammen med depth-kolonnen til å sette mellomrom foran hvert navn, slik at vi får en tekstbasert trevisning.

WITH RECURSIVE category_tree AS (
  SELECT id, name, parent_id, 0 AS depth
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  SELECT c.id, c.name, c.parent_id, ct.depth + 1
  FROM   categories    c
  JOIN   category_tree ct ON ct.id = c.parent_id
)
SELECT
  REPEAT('    ', depth) || name AS indented_name,
  depth
FROM   category_tree
ORDER  BY path;

Beskytte mot uendelige løkker

Hvis dataene inneholder en syklus (A er forelder til B, B er forelder til A), vil rekursjonen kjøre for alltid og krasje. Du kan beskytte mot dette ved å spore besøkte ID-er i en array og stoppe når gjeldende ID allerede finnes i den.

WITH RECURSIVE safe_tree AS (
  SELECT id, name, parent_id,
         ARRAY[id] AS visited
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  SELECT c.id, c.name, c.parent_id,
         st.visited || c.id
  FROM   categories c
  JOIN   safe_tree  st ON st.id = c.parent_id
  WHERE  c.id <> ALL(st.visited)   -- stop if already seen
)
SELECT id, name FROM safe_tree;

Telle etterkommere per node

Når du har hele treet, kan du aggregere det. Her teller vi hvor mange etterkommere hver node har, ved å gruppere barneradene mot listen over forfedre igjen. Dette er nyttig når du vil vise antall elementer ved siden av kategorinavn i en navigasjonsmeny.

WITH RECURSIVE category_tree AS (
  SELECT id, name, parent_id, id AS root_id
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  SELECT c.id, c.name, c.parent_id, ct.root_id
  FROM   categories    c
  JOIN   category_tree ct ON ct.id = c.parent_id
)
SELECT
  root_id,
  COUNT(*) - 1 AS descendant_count
FROM   category_tree
GROUP  BY root_id
ORDER  BY root_id;

Hurtigsjekk

Test forståelsen av rekursive spørringer for kategoritrær.

Oppsummering av leksjonen

I denne leksjonen lærte du hvordan du kan gå gjennom en selvrefererende kategoritabell ved hjelp av WITH RECURSIVE.

Viktigste punkter:

- Ankerdelen velger startnodene (vanligvis roten).

- Den rekursive delen kobler CTE-en tilbake til basistabellen for å finne neste nivå.

- Legg til en depth-kolonne for å spore hvor mange nivåer dypt hver node ligger.

- Bygg en path-streng for å generere brødsmulestier.

- Gå oppover ved å følge parent_id i motsatt retning for å finne alle forfedrene.

- Bruk en visited-array for å beskytte mot sykluser i uryddige data.

Gratis å komme i gang

Lær deg SQL med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
46
Leksjoner
183

Ofte stilte spørsmål

Er leksjonen «Gå gjennom et kategoritre» gratis?

Ja – hele teksten i «Gå gjennom et kategoritre» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av SQL Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Gå gjennom et kategoritre»?

Utvid foreldre-barn-trær fullstendig. Du øver på SQL Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med SQL Academy?

Ingen tidligere erfaring er nødvendig. SQL Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Gå gjennom et kategoritre»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne SQL Academy-leksjonen?

Ja. Alle SQL Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Slik fungerer rekursive CTE-er
  2. Gå gjennom et kategoritre
  3. Generere serier og sekvenser
  4. Unngå uendelige løkker
← Tilbake til SQL Academy