Pregunta formulada
Usted no puede hacer referencia a un alias de tabla de una subconsulta en otra consulta en el mismo nivel (o en otro tramo de una UNION
consulta). Un alias de tabla solo es visible en la consulta misma y en las subconsultas de la misma.
Usted podría columnas de salida de referencia de una subconsulta en el mismo nivel de consulta con un LATERAL JOIN
. Ejemplo:
Encuentre los elementos más comunes en una matriz con un grupo por
Solución para un pequeño número máximo de niveles
Por solo un puñado de niveles (si sabes el máximo), puede usar una consulta simple:
LEFT JOIN
a n-1 instancias de la propia tabla- Usar
COALESCE
y unCASE
declaración para precisar la raíz y la 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 es SQL estándar y debería funcionar en los 4 RDBMS has etiquetado.
Solución genérica para un número arbitrario de niveles
Use un CTE recursivo como @Ken ya aconsejó.
- En la pierna recursiva mantener al niño para cada fila, solo avance el padre.
- En el exterior
SELECT
, solo mantén la fila con la mayorheight
por niño.
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
es específico de Postgres . Explicación:
¿Seleccionar la primera fila en cada grupo GROUP BY?
El resto funcionaría de manera similar en Oracle e incluso SQLite , pero no en MySQL, que no admite CTE.
SQL Fiddle demostrando ambos.