Položená otázka
Nemůžete odkazovat na alias tabulky z jednoho poddotazu v jiném dotazu na stejné úrovni (nebo v jiné části UNION
dotaz). Alias tabulky je viditelný pouze v samotném dotazu a jeho dílčích dotazech.
To byste mohli odkazovat na výstupní sloupce poddotazu na stejné úrovni dotazu pomocí LATERAL JOIN
. Příklad:
Najít nejběžnější prvky v poli se skupinou podle
Řešení pro malý maximální počet úrovní
Pouze pro několik úrovní (pokud víte maximum), můžete použít jednoduchý dotaz:
LEFT JOIN
na n-1 instancí samotné tabulky- Použijte
COALESCE
aCASE
příkaz k určení kořene a výšky,
SELECT p1.c AS child, COALESCE(p3.p, p2.p, p1.p) AS parent
,CASE
WHEN p3.p IS NOT NULL THEN 3
WHEN p2.p IS NOT NULL THEN 2
ELSE 1
END AS height
FROM parent p1
LEFT JOIN parent p2 ON p2.c = p1.p
LEFT JOIN parent p3 ON p3.c = p2.p
WHERE p1.c IN (3, 8)
ORDER BY p1.c;
Toto je standardní SQL a mělo by fungovat ve všech 4 RDBMS jste označili.
Obecné řešení pro libovolný počet úrovní
Použijte rekurzivní CTE jako již poradil @Ken.
- V rekurzivní větvi udržet dítě pro každý řádek posuňte pouze nadřazený prvek.
- Ve vnějším
SELECT
, ponechte pouze řádek s největšíheight
na dítě.
WITH RECURSIVE cte AS (
SELECT c AS child, p AS parent, 1 AS height
FROM parent
WHERE c IN (3, 8)
UNION ALL
SELECT c.child, p.p AS parent, c.height + 1
FROM cte c
JOIN parent p ON p.c = c.parent
-- WHERE c.height < 10 -- to safeguard against endless loops if necessary
)
SELECT DISTINCT ON (child) *
FROM cte
ORDER BY child, height DESC;
DISTINCT ON
je specifické pro Postgres . Vysvětlení:
Vybrat první řádek v každé skupině GROUP BY?
Zbytek by fungoval podobným způsobem v Oraclu a dokonce SQLite , ale ne v MySQL, která nepodporuje CTE.
SQL Fiddle předvedení obojího.