Przejdź do głównej treści
eLearner.app
Moduł 5 · Lekcja 2 z 418/57 w kursie~10 min
Lekcje modułu (2/4)

Self-JOIN: tabela z samą sobą

Czasami związek, który chcesz przejść, nie jest pomiędzy dwojgiem ludzi różnych tabel, ale pomiędzy wierszami tej samej tabeli. Typowy przykład: Hierarchia „kategoria → podkategoria”, w której zarówno rodzic, jak i dziecko są wierszami ta sama tabela categories, połączona przez parent_id.

Aby przeczytać razem jeden wiersz (dziecko) i „jego” drugi wiersz (rodzic), użyj a samołączenie: ta sama tabela pojawia się dwukrotnie w FROM, z dwoma różne pseudonimy.

Składnia

SQL
SELECT colonne
FROM   tabella AS alias_a
JOIN   tabella AS alias_b ON alias_a.foreign_key = alias_b.id;

Alias jest obowiązkowy: jeśli pominiemy AS a / AS b, PostgreSQL nie będzie miał sposób wiedzieć, którą z dwóch kopii mamy na myśli, pisząc name lub id.

SQL
-- Ogni sotto-categoria con il nome della categoria padre:
SELECT child.name  AS subcategory,
       parent.name AS category
FROM   categories AS child
JOIN   categories AS parent ON child.parent_id = parent.id;

Przeczytaj prostym angielskim: ”weź wiersze categories o nazwie dziecko i dla każdego znajdź wiersz categories o nazwie parent, którego id to KODPH3 dziecka”.

Wynik wyklucza kategorie główne (te z parent_id = NULL) ponieważ INNER JOIN pomija wiersze bez dopasowania. Jeśli chcesz uwzględnić nich, użyj LEFT JOIN.

Samodołączenie za pomocą LEWEGO, aby „zachować korzenie”

SQL
-- Tutte le categorie, con nome del padre o NULL se sono radice:
SELECT child.name AS category,
       parent.name AS parent
FROM   categories AS child
LEFT JOIN categories AS parent ON child.parent_id = parent.id;

Teraz otrzymujesz 9 wierszy (każda kategoria w zestawie danych) z parent = NULL dla 3 korzeni.

Agregowanie przy użyciu samodzielnego łączenia

Bardzo dobrze łączy się z GROUP BY, aby zapytać „ile dzieci robi każde z nich rodzic ma":

SQL
SELECT p.name AS parent_category,
       COUNT(c.id) AS children
FROM   categories AS p
LEFT JOIN categories AS c ON c.parent_id = p.id
WHERE  p.parent_id IS NULL          -- solo le radici
GROUP BY p.name
ORDER BY p.name;

Zwróć uwagę na dwa ważne szczegóły:

  1. Filtry WHERE p.parent_id IS NULL przed DOŁĄCZENIEM: bierzemy tylko korzenie jako „stół po lewej stronie”.
  2. COUNT(c.id) (nie COUNT(*)) zwraca 0 dla pierwiastków bez dzieci, podczas gdy COUNT(*) zwróci 1 z powodu wiersza LEFT JOIN NULL.

Spróbuj sam

Ćwiczenie#sql.m5.l2.e1
Próby: 0Ładowanie...

Dla każdej kategorii (kategoria z identyfikatorem nadrzędnym NOT NULL), większość nazw kategorii jest nazywana kategorią padre. Due colonne: podkategoria, kategoria. Ordina według kategorii poi dla podkategorii.

Ładowanie edytora...
Pokaż wskazówkę

Warunek samodzielnego dołączenia to child.parent_id = parent.id.

Rozwiązanie dostępne po 3 próbach

Przejrzyj ćwiczenie

Ćwiczenie#sql.m5.l2.e2
Próby: 0Ładowanie...

Dla każdej kategorii-radice (parent_id IS NULL), mostra il nome i numero di sotto-categorie. Due colonne: imię, dzieci. Ordina na imię. Zawiera ewentualną radice senza figlie con 0.

Ładowanie edytora...
Pokaż wskazówkę

LEFT JOIN w kategoriach dwukrotnie (alias p dla elementu nadrzędnego, c dla elementu podrzędnego). Użyj COUNT(c.id), a nie COUNT(*), aby uzyskać 0 w korzeniach bez dzieci.

Rozwiązanie dostępne po 3 próbach