Zadane pytanie
nie możesz odwołać się do aliasu tabeli z jednego podzapytania w innym zapytaniu na tym samym poziomie (lub w innej gałęzi UNION
zapytanie). Alias tabeli jest widoczny tylko w samym zapytaniu i jego podzapytaniach.
Możesz mógł odwołaj się do kolumn wyjściowych podzapytania na tym samym poziomie zapytania z LATERAL JOIN
. Przykład:
Znajdź najczęstsze elementy w tablicy z grupą według
Rozwiązanie dla małej maksymalnej liczby poziomów
Tylko dla kilku poziomów (jeśli wiesz maksimum), możesz użyć prostego zapytania:
LEFT JOIN
do n-1 instancji samej tabeli- Użyj
COALESCE
iCASE
oświadczenie określające korzeń i wysokość,
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;
To jest standardowy SQL i powinien działać we wszystkich 4 RDBMS oznaczyłeś.
Ogólne rozwiązanie dla dowolnej liczby poziomów
Użyj rekurencyjnego CTE jak już radził @Ken.
- W odnodze rekurencyjnej trzymaj dziecko dla każdego rzędu przesuwaj tylko rodzica.
- W zewnętrznym
SELECT
, zachowaj tylko wiersz o największejheight
na dziecko.
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
jest specyficzny dla Postgresu . Wyjaśnienie:
Wybrać pierwszy wiersz w każdej grupie GROUP BY?
Reszta działałaby w podobny sposób w Oracle a nawet SQLite , ale nie w MySQL, który nie obsługuje CTE.
Skrzypce SQL demonstrując oba.