sql >> データベース >  >> RDS >> Oracle

別のクエリでテーブルエイリアスを使用してツリーをトラバースします

    質問

    できません テーブルエイリアスを参照する 同じレベルの別のクエリ(または UNION の別のレッグ)の1つのサブクエリから クエリ)。テーブルエイリアスは、クエリ自体とそのサブクエリにのみ表示されます。
    できた LATERAL JOIN 。例:
    groupbyを使用して配列内の最も一般的な要素を検索

    レベルの最大数が少ない場合の解決策

    ほんの一握りのレベル(知っている場合 最大)、簡単なクエリを使用できます:

    • LEFT JOIN テーブル自体のn-1インスタンスへ
    • COALESCEを使用する およびCASE ルートとハイトを特定するステートメント
    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;
    

    これは標準SQLであり、4つのRDBMSすべてで機能するはずです。 タグを付けました。

    任意の数のレベルの一般的なソリューション

    再帰CTE を使用します @Kenのようにすでにアドバイスされています。

    • 再帰的な脚で子供を飼う すべての行について、親のみを進めます。
    • 外側のSELECT heightが最大の行のみを保持します 子供1人あたり。
    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 Postgresに固有です 。説明:
    各GROUPBYグループの最初の行を選択しますか?

    残りはOracleでも同様に機能します そしてSQLite 、ただし、CTEをサポートしないMySQLにはありません。

    SQLフィドル 両方を示しています。



    1. 11gR2圧縮アドバイザー=悪

    2. 時間を時間単位または 10 分単位でグループ化する方法

    3. SQLサーバー2008で地理ポリゴンを検​​証する方法は?

    4. postgresqlとの奇妙な照合