Pergunta feita
Você não pode referenciar um alias de tabela de uma subconsulta em outra consulta no mesmo nível (ou em outra perna de um
UNION
consulta). Um alias de tabela só é visível na própria consulta e nas subconsultas dela.Você poderia colunas de saída de referência de uma subconsulta no mesmo nível de consulta com um
LATERAL JOIN
. Exemplo:Encontre os elementos mais comuns na matriz com um grupo por
Solução para um pequeno número máximo de níveis
Por apenas alguns níveis (se você saber o máximo), você pode usar uma consulta simples:
LEFT JOIN
para n-1 instâncias da própria tabela- Usar
COALESCE
e umCASE
declaração para definir a raiz e a altura,
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;
Este é o SQL padrão e deve funcionar em todos os 4 RDBMS você marcou.
Solução genérica para um número arbitrário de níveis
Use um CTE recursivo como @Ken já aconselhou.
- Na perna recursiva mantenha a criança para cada linha, avance apenas o pai.
- No
SELECT
externo , mantenha apenas a linha com a maiorheight
por criança.
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
é específico do Postgres . Explicação:Selecionar a primeira linha em cada grupo GROUP BY?
O resto funcionaria de maneira semelhante no Oracle e até mesmo SQLite , mas não no MySQL que não suporta CTEs.
SQL Fiddle demonstrando ambos.