sql >> Database >  >> RDS >> Oracle

Tabelalias gebruiken in een andere query om een ​​boomstructuur te doorlopen

Vraag gesteld

Je kan niet verwijzen naar een tabelalias van de ene subquery in een andere query op hetzelfde niveau (of in een ander deel van een UNION vraag). Een tabelalias is alleen zichtbaar in de query zelf en subquery's ervan.
U zou referentie-uitvoerkolommen van een subquery op hetzelfde queryniveau met een LATERAL JOIN . Voorbeeld:
Vind de meest voorkomende elementen in een array met een groep op

Oplossing voor een klein maximum aantal niveaus

Voor slechts een handvol niveaus (als je weet het maximum), kunt u een eenvoudige zoekopdracht gebruiken:

  • LEFT JOIN tot n-1 instanties van de tabel zelf
  • Gebruik COALESCE en een CASE statement om de wortel en hoogte vast te pinnen,
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;

Dit is standaard SQL en zou in alle 4 RDBMS moeten werken je hebt getagd.

Algemene oplossing voor willekeurig aantal niveaus

Gebruik een recursieve CTE zoals @Ken al heeft geadviseerd.

  • In het recursieve been het kind houden voor elke rij, alleen de ouder vooruit.
  • In de buitenste SELECT , bewaar alleen de rij met de grootste height per 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 is specifiek voor Postgres . Uitleg:
Selecteer de eerste rij in elke GROUP BY-groep?

De rest zou op een vergelijkbare manier werken in Oracle en zelfs SQLite , maar niet in MySQL die geen CTE's ondersteunt.

SQL Fiddle beide demonstreren.



  1. Formaat MySQL-querylogdatum

  2. Is er een functie in MySQL die de resultaten van een query comprimeert?

  3. Meerdere rijen retourneren op één record

  4. Oracle-tabel of weergave bestaat niet vanuit de opgeslagen procedure