Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Verwenden Sie den Tabellenalias in einer anderen Abfrage, um einen Baum zu durchlaufen

Frage gestellt

Das können Sie nicht einen Tabellenalias referenzieren von einer Unterabfrage in einer anderen Abfrage auf der gleichen Ebene (oder in einem anderen Zweig einer UNION Anfrage). Ein Tabellenalias ist nur in der Abfrage selbst und Unterabfragen davon sichtbar.
Sie könnten Verweisen Sie auf Ausgabespalten einer Unterabfrage auf derselben Abfrageebene mit einem LATERAL JOIN . Beispiel:
Finden Sie die häufigsten Elemente in einem Array mit einer Gruppierung nach

Lösung für kleine maximale Levelanzahl

Für nur eine Handvoll Level (wenn Sie wissen das Maximum), können Sie eine einfache Abfrage verwenden:

  • LEFT JOIN auf n-1 Instanzen der Tabelle selbst
  • Verwenden Sie COALESCE und ein CASE Anweisung, um die Wurzel und die Höhe festzulegen,
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;

Dies ist Standard-SQL und sollte in allen 4 RDBMS funktionieren du getaggt hast.

Generische Lösung für beliebig viele Ebenen

Verwenden Sie einen rekursiven CTE wie @Ken bereits empfohlen hat.

  • Im rekursiven Bein behalte das Kind für jede Zeile nur das übergeordnete Element vorrücken.
  • Im äußeren SELECT , behalten Sie nur die Zeile mit der größten height pro Kind.
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 ist spezifisch für Postgres . Erklärung:
Erste Zeile in jeder GROUP BY-Gruppe auswählen?

Der Rest würde in Oracle auf ähnliche Weise funktionieren und sogar SQLite , aber nicht in MySQL, das CTEs nicht unterstützt.

SQL-Fiddle demonstriert beides.