2012-05-11 15 views
7

के सभी आइटमों को रिकर्सिवली रूप से प्राप्त करता है मेरे पास 2 टेबल हैं। items और itemItemsक्या SQLite क्वेरी लिखना संभव है जो रूट आइटम नोड

itemItemsitems के बीच कई रिश्तों का वर्णन करता है। अर्थात। items के एक सदस्य के कई बच्चे हैं और वे कई बच्चों जो बारी में कई बच्चों आदि हो सकता है हो सकता है हो सकता है ..

आइटम:

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

itemItems:

parentItemID | childItemID 
1    2 
1    3 
2    4 

मैं एक प्रश्न लिखना चाहता हूं जो सभी बच्चों को एक रूट नोड के नीचे दोबारा मिल जाएगा।

मेरा मानना ​​है कि यह कुछ एक पुनरावर्ती में शामिल होने के कहा जाता है के साथ संभव है, लेकिन मैं अवधारणा बहुत भ्रामक .... लगता है (this प्रश्न के समान है, लेकिन कई लोगों के लिए SQLite एसक्यूएल सर्वर नहीं है और कई नहीं एक के लिए कई के साथ)

मैं मैं कैसे का विस्तार कर सकता है इस रिकर्सिवली सभी बच्चों के बच्चों आदि प्राप्त करने के लिए निम्नलिखित

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

करके प्रथम स्तर (यानी एक मद के अंतर्गत सभी बच्चों) प्राप्त कर सकते हैं ...?

उत्तर

8

मैं सिर्फ with recursive सिंटैक्स का उपयोग काम करने के लिए एक समान क्वेरी मिल गया। सामान्य रूप है:

with recursive tc(i) 
    as (select [... initial-query ...] 
     union [... recursive-part (include tc) ...] 
    ) 
select * from 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-डेटाबेस भी। –

+1

@AndrewEidsness इसे 3.7.2 में कैसे काम करें? – kiran

1

पुनरावर्ती संस्करण ऊपर ANSI SQL की आवश्यकता है: 1999 जो उन दिनों में आम डीबीएमएस के द्वारा समर्थित है, लेकिन वहाँ भी घिरा प्रत्यावर्तन प्राप्त करने के लिए एक एएनएसआई 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 
संबंधित मुद्दे