Domanda posta
non puoi fare riferimento a un alias di tabella da una sottoquery in un'altra query allo stesso livello (o in un'altra parte di un UNION
interrogazione). Un alias di tabella è visibile solo nella query stessa e nelle sue sottoquery.
Potresti potere fare riferimento alle colonne di output di una sottoquery sullo stesso livello di query con un LATERAL JOIN
. Esempio:
Trova gli elementi più comuni nell'array con un gruppo per
Soluzione per un piccolo numero massimo di livelli
Solo per una manciata di livelli (se sai il massimo), puoi utilizzare una semplice query:
LEFT JOIN
a n-1 istanze della tabella stessa- Usa
COALESCE
e unCASE
dichiarazione per definire la radice e l'altezza,
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;
Questo è un SQL standard e dovrebbe funzionare in tutti e 4 gli RDBMS hai taggato.
Soluzione generica per un numero arbitrario di livelli
Utilizzare un CTE ricorsivo come @Ken già consigliato.
- Nella gamba ricorsiva tieni il bambino per ogni riga, fai avanzare solo il genitore.
- Nel
SELECT
esterno , mantieni solo la riga con l'height
maggiore per bambino.
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
è specifico di Postgres . Spiegazione:
Selezionare la prima riga in ogni gruppo GROUP BY?
Il resto funzionerebbe in modo simile in Oracle e persino SQLite , ma non in MySQL che non supporta i CTE.
SQL Fiddle dimostrando entrambi.