Fråga ställd
Du kan inte referera till ett tabellalias från en underfråga i en annan fråga på samma nivå (eller i en annan del av en UNION
fråga). Ett tabellalias är bara synligt i själva frågan och underfrågor till den.
Du kunde referera utdatakolumner för en underfråga på samma frågenivå med en LATERAL JOIN
. Exempel:
Hitta de vanligaste elementen i array med en grupp av
Lösning för litet maximalt antal nivåer
För bara en handfull nivåer (om du vet). maximalt), kan du använda en enkel fråga:
LEFT JOIN
till n-1 instanser av själva tabellen- Använd
COALESCE
och enCASE
uttalande för att fästa roten och höjden,
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;
Detta är standard SQL och bör fungera i alla fyra RDBMS du taggade.
Generisk lösning för godtyckligt antal nivåer
Använd en rekursiv CTE som @Ken redan har tipsat om.
- I det rekursiva benet håll barnet för varje rad, flytta bara föräldern.
- I den yttre
SELECT
, behåll bara raden med den störstaheight
per barn.
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
är specifik för Postgres . Förklaring:
Välj första raden i varje GROUP BY-grupp?
Resten skulle fungera på liknande sätt i Oracle och till och med SQLite , men inte i MySQL som inte stöder CTE.
SQL Fiddle demonstrerar båda.