2012-05-11 6 views
7

2つのテーブルがあります。 itemsおよびitemItemsルートノードの子アイテムであるすべてのアイテムを再帰的に取得するSQLiteクエリを書くことは可能ですか

itemItemsは、itemsの多対多の関係を記述する。私。 itemsのメンバーは、多くの子供を持つことができ、彼らは順番に多くの子供などを持っている可能性が多くの子供を持つことができます。..

項目:

itemID | more stuff ...... 
1   ...  
2   ... 
3   ... 
4   ... 

itemItems:

parentItemID | childItemID 
1    2 
1    3 
2    4 

私は再帰的に1つのルートノードの下にすべての子を取得するクエリを記述したい。

私は、これは参加再帰と呼ばれるもので可能であると考えているが、私は非常に混乱コンセプト....見つける(this質問に類似するが、多くの多くはないものとSQLiteのSQLサーバーではなく、多くの付き)

私は、これは再帰的になど、すべての子供たちの子供たちを取得するために拡張することができる方法

私は...次

SELECT * 
FROM items 
INNER JOIN itemItems 
ON items.itemID = itemItems.childItemID 
WHERE itemItems.parentItemID = 1 

を実行して、最初のレベル(1つの項目の下、すなわち、すべての子供を)得ることができますか?

答えて

8

私はちょうどwith recursive構文を使用して動作するように類似したクエリを得ました。一般的な形式は次のとおりです。私の場合は

with recursive tc(i) 
    as (select [... initial-query ...] 
     union [... recursive-part (include tc) ...] 
    ) 
select * from tc; 

キーTcが再帰部分に記載されていたことを確認しました。また、この最終的な選択は、推移閉包の完全な内容を表示することに過ぎず、実際の内容は必要な行を選択する必要があります。

このレシピは次のようにあなたのケースに当てはまると思います。私はこれをテストしていない、私はちょうど私のクエリから貼り付けるとあなたのテーブル名で置き換えています。それは私のために働くが、私はこれを間違って翻訳したかもしれない。私は効率などについても本当に分かりません。それは私が働かなければならないものです。

with recursive tc(i) 
    as (select childItemID from itemItems where parentItemID = 1 
     union select childItemID from itemItems, tc 
       where itemItems.parentItemID = tc.i 
    ) 
    select * from item where itemID in tc; 

注:これはバージョン3.8.3.1では動作しましたが、3.7.2では動作しませんでした。

+0

この領域の周りのテキストhttps://sqlite.org/lang_with.html#rcex1は、特に「階層的なクエリの例」セクションの作業に役立ちました。また、一般的な概念についてはhttp://www.sitepoint.com/hierarchical-data-databaseを参照してください。 –

+1

@ AndrewEidsness 3.7.2で動作させるには? – kiran

1

上記の再帰バージョンでは、当時は一般的なDBMSでサポートされていたANSI SQL:1999が必要でしたが、をバインドしたの再帰を実現するANSI SQL-92メソッドもあります。このアプローチは任意に拡張することができます。

以下の例は、最大7つのレベルをサポートしています。あなたがもっとしたい場合は、もっと追加してください。

SELECT DISTINCT 
    I.* 
FROM 
    item I INNER JOIN (
     SELECT 
      I1.itemID as Level1, 
      I2.itemID as Level2, 
      I3.itemID as Level3, 
      I4.itemID as Level4, 
      I5.itemID as Level5, 
      I6.itemID as Level6, 
      I7.itemID as Level7 
     FROM 
      item I1 LEFT JOIN 
      item I2 ON EXISTS (SELECT NULL FROM itemItems II1 WHERE II1.parentItemID = I1.itemID AND I2.itemID = II1.childItemID) LEFT JOIN 
      item I3 ON EXISTS (SELECT NULL FROM itemItems II2 WHERE II2.parentItemID = I2.itemID AND I3.itemID = II2.childItemID) LEFT JOIN 
      item I4 ON EXISTS (SELECT NULL FROM itemItems II3 WHERE II3.parentItemID = I3.itemID AND I4.itemID = II3.childItemID) LEFT JOIN 
      item I5 ON EXISTS (SELECT NULL FROM itemItems II4 WHERE II4.parentItemID = I4.itemID AND I5.itemID = II4.childItemID) LEFT JOIN 
      item I6 ON EXISTS (SELECT NULL FROM itemItems II5 WHERE II5.parentItemID = I5.itemID AND I6.itemID = II5.childItemID) LEFT JOIN 
      item I7 ON EXISTS (SELECT NULL FROM itemItems II6 WHERE II6.parentItemID = I6.itemID AND I7.itemID = II6.childItemID) 
     WHERE 
      I1.itemID = 1 -- root node condition 
    ) D ON I.itemID = D.Level1 OR I.itemID = D.Level2 OR I.itemID = D.Level3 OR I.itemID = D.Level4 OR I.itemID = D.Level5 OR I.itemID = D.Level6 Or I.itemID = D.Level7 
関連する問題