sql >> Databáze >  >> RDS >> Oracle

Použijte alias tabulky v jiném dotazu k procházení stromu

Položená otázka

Nemůžete odkazovat na alias tabulky z jednoho poddotazu v jiném dotazu na stejné úrovni (nebo v jiné části UNION dotaz). Alias ​​tabulky je viditelný pouze v samotném dotazu a jeho dílčích dotazech.
To byste mohli odkazovat na výstupní sloupce poddotazu na stejné úrovni dotazu pomocí LATERAL JOIN . Příklad:
Najít nejběžnější prvky v poli se skupinou podle

Řešení pro malý maximální počet úrovní

Pouze pro několik úrovní (pokud víte maximum), můžete použít jednoduchý dotaz:

  • LEFT JOIN na n-1 instancí samotné tabulky
  • Použijte COALESCE a CASE příkaz k určení kořene a výšky,
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;

Toto je standardní SQL a mělo by fungovat ve všech 4 RDBMS jste označili.

Obecné řešení pro libovolný počet úrovní

Použijte rekurzivní CTE jako již poradil @Ken.

  • V rekurzivní větvi udržet dítě pro každý řádek posuňte pouze nadřazený prvek.
  • Ve vnějším SELECT , ponechte pouze řádek s největší height na dítě.
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 je specifické pro Postgres . Vysvětlení:
Vybrat první řádek v každé skupině GROUP BY?

Zbytek by fungoval podobným způsobem v Oraclu a dokonce SQLite , ale ne v MySQL, která nepodporuje CTE.

SQL Fiddle předvedení obojího.



  1. Porovnání Load Balancerů pro PostgreSQL

  2. SQL_CALC_FOUND_ROWS / FOUND_ROWS() nefunguje v PHP

  3. Pořiďte si svůj vlastní cloud dostupný pro DigitalOcean

  4. MySQL Limit LEFT JOIN Poddotaz po připojení