2008-09-12 20 views
7

मेरे पास अगली टेबल हैं। समूह तालिका जिसमें श्रेणीबद्ध क्रमबद्ध समूह और group_member शामिल हैं जो उपयोगकर्ता को किस समूह से संबंधित करता है।एसक्यूएल रिकर्सन

groups 
--------- 
id 
parent_id 
name 

group_member 
--------- 
id 
group_id 
user_id 

ID PARENT_ID NAME 
--------------------------- 
1 NULL  Cerebra 
2 1   CATS 
3 2   CATS 2.0 
4 1   Cerepedia 
5 4   Cerepedia 2.0 
6 1   CMS 

ID GROUP_ID USER_ID 
--------------------------- 
1 1  3 
2 1  4 
3 1  5 
4 2  7 
5 2  6 
6 4  6 
7 5  12 
8 4  9 
9 1  10 

मैं किसी दिए गए उपयोगकर्ता के लिए दृश्य समूह पुनर्प्राप्त करना चाहता हूं। यह उन समूहों को कहना है जो उपयोगकर्ता इन समूहों के हैं और बच्चे हैं। उदाहरण के लिए, उपर्युक्त डेटा के साथ:

USER VISIBLE_GROUPS 
9  4, 5 
3  1,2,4,5,6 
12 5 

मुझे रिकर्सन और कई डेटाबेस क्वेरीज़ का उपयोग करके ये मान मिल रहे हैं। लेकिन मैं जानना चाहता हूं कि मेरे ऐप प्रदर्शन को बेहतर बनाने के लिए एक SQL क्वेरी के साथ ऐसा करना संभव है या नहीं। मैं MySQL का उपयोग कर रहा हूँ।

उत्तर

0

मुझे लगता है कि आप इस के लिए कर्सर, this link मदद मिल सकती है

+0

कोडप्रोजेक्ट लिंक SQL सर्वर के लिए लिखा गया है। MySQL के लिए उस कोड को अनुकूलित करना आसान नहीं हो सकता है, लेकिन यहां कर्सर पर mySQL संदर्भ है: http://dev.mysql.com/doc/refman/5.0/en/cursors.html – Prestaul

0

जरूरत के लिए मुझे नहीं लगता कि इस प्रत्यावर्तन का उपयोग किए बिना पूरा किया जा सकता है जा रहे हैं। आप इसे MySQL का उपयोग करके एक संग्रहीत प्रक्रिया के साथ पूरा कर सकते हैं, लेकिन डिफ़ॉल्ट रूप से संग्रहित प्रक्रियाओं में रिकर्सन की अनुमति नहीं है। This article में रिकर्सन को सक्षम करने के तरीके के बारे में जानकारी है। मैं इस बारे में निश्चित नहीं हूं कि प्रदर्शन क्वेरी पर एकाधिक प्रभाव दृष्टिकोण पर इसका कितना असर होगा। mySQL संग्रहित प्रक्रियाओं के कुछ अनुकूलन कर सकता है, लेकिन अन्यथा मैं प्रदर्शन की अपेक्षा करता हूं।

0

यदि आप एक उपयोगकर्ता तालिका था नहीं पता था, इसलिए मैं user_id के Group_Member तालिका में संग्रहीत के माध्यम से सूची प्राप्त ...

SELECT GroupUsers.User_ID, 
     (
     SELECT 
      STUFF((SELECT ',' + 
      Cast(Group_ID As Varchar(10)) 
      FROM Group_Member Member (nolock) 
      WHERE Member.User_ID=GroupUsers.User_ID 
     FOR XML PATH('')),1,1,'') 
     ) As Groups 
FROM (SELECT User_ID FROM Group_Member GROUP BY User_ID) GroupUsers 

देता है कि:

User_ID Groups 
3   1 
4   1 
5   1 
6   2,4 
7   2 
9   4 
10   1 
12   5 

कौन सा लगता है आपकी तालिका में डेटा के अनुसार सही। लेकिन आपकी अपेक्षित मूल्य सूची से मेल नहीं खाता है (उदाहरण के लिए उपयोगकर्ता 9 केवल आपके तालिका डेटा में एक समूह में है, लेकिन आप इसे परिणामों में दिखाते हैं क्योंकि दो)

संपादित करें: डांग। बस ध्यान दिया कि आप MySQL का उपयोग कर रहे हैं। मेरा समाधान SQL सर्वर के लिए था। माफ़ कीजिये।

- केविन फेयरचाइल्ड

-1

SQL मानक में यह करने के लिए कोई तरीका नहीं है, लेकिन आप आमतौर पर Oracle में, विक्रेता विशिष्ट एक्सटेंशन, जैसे पा सकते हैं CONNECT BY। आप बार-बार खुद को रिकर्सिवली करने के लिए तालिका बाहरी-शामिल हो सकते हैं -

1:

अद्यतन: जैसा कि टिप्पणियों का कहना है, इस एसक्यूएल 99

+0

गलत। आईएसओ एसक्यूएल मानक एसक्यूएल: 1 999 मानक के बाद रिकर्सिव एसक्यूएल निर्दिष्ट किया गया है। डीबी 2 और एमएसएसएलएल के हाल के संस्करण इसे लागू करते हैं। एसक्यूएल मानक का रिकर्सिव एसक्यूएल ओरेकल के कनेक्ट से अलग है, वैसे भी। –

+0

मुझे इसका एहसास नहीं हुआ। क्या नवीनतम मानकों के लिए एक मुफ्त संदर्भ है, क्योंकि आईएसओ स्पष्ट रूप से सोचता है कि डेवलपर्स को मानक के लिए भुगतान करना चाहिए? –

6

दो बातें में जोड़ा गया मन के लिए आते हैं अपने पेड़ पर चलते हैं, के रूप में:

SELECT * 
FROM 
    MY_GROUPS MG1 
,MY_GROUPS MG2 
,MY_GROUPS MG3 
,MY_GROUPS MG4 
,MY_GROUPS MG5 
,MY_GROUP_MEMBERS MGM 
WHERE MG1.PARENT_ID = MG2.UNIQID (+) 
    AND MG1.UNIQID = MGM.GROUP_ID (+) 
    AND MG2.PARENT_ID = MG3.UNIQID (+) 
    AND MG3.PARENT_ID = MG4.UNIQID (+) 
    AND MG4.PARENT_ID = MG5.UNIQID (+) 
    AND MGM.USER_ID = 9 

यही है वाला आप परिणाम इस तरह दे:

UNIQID PARENT_ID NAME  UNIQID_1 PARENT_ID_1 NAME_1 UNIQID_2 PARENT_ID_2 NAME_2 UNIQID_3 PARENT_ID_3 NAME_3 UNIQID_4 PARENT_ID_4 NAME_4 UNIQID_5 GROUP_ID USER_ID 
4  2   Cerepedia 2  1   CATS 1  null  Cerebra null  null  null null  null  null 8  4  9 

यहां सीमा यह है कि आपको प्रत्येक "स्तर" के लिए एक नया जुड़ना जोड़ना चाहिए जिसे आप पेड़ पर चलना चाहते हैं। यदि आपके पेड़ से 20 स्तर कम हैं, तो आप शायद एक दृश्य बनाकर इसे दूर कर सकते हैं जो प्रत्येक उपयोगकर्ता से 20 स्तर दिखाता है।

2 - एकमात्र अन्य दृष्टिकोण जिसे मैं जानता हूं वह एक रिकर्सिव डेटाबेस फ़ंक्शन बनाना है, और उसे कोड से कॉल करना है। आपके पास अभी भी कुछ लुकअप ओवरहेड होगा (यानी, आपके # प्रश्न अभी भी पेड़ पर चल रहे स्तरों के # के बराबर होंगे), लेकिन समग्र रूप से यह डेटाबेस के भीतर होने के बाद से तेज़ होना चाहिए।

मुझे माईएसक्ल के बारे में निश्चित नहीं है, लेकिन ओरेकल में, ऐसा फ़ंक्शन इस जैसा होगा (आपको टेबल और फ़ील्ड नामों को बदलना होगा; मैं बस अतीत में कुछ कॉपी कर रहा हूं) :

CREATE OR REPLACE FUNCTION GoUpLevel(WO_ID INTEGER, UPLEVEL INTEGER) RETURN INTEGER 
IS 
BEGIN 
    DECLARE 
    iResult INTEGER; 
    iParent INTEGER; 
BEGIN 
    IF UPLEVEL <= 0 THEN 
    iResult := WO_ID; 
    ELSE 
    SELECT PARENT_ID 
    INTO iParent 
    FROM WOTREE 
    WHERE ID = WO_ID;  
    iResult := GoUpLevel(iParent,UPLEVEL-1); --recursive 
    END; 
    RETURN iResult; 
    EXCEPTION WHEN NO_DATA_FOUND THEN 
    RETURN NULL; 
    END; 
END GoUpLevel; 
/
3

जो Cleko की किताबें "Smarties के लिए एसक्यूएल में पेड़ों और पदानुक्रम" "Smarties के लिए एसक्यूएल" और तरीकों कि प्रत्यावर्तन पूरी तरह से बचने का वर्णन है, नेस्टेड सेट का उपयोग करके। यह अद्यतन को जटिल बनाता है, लेकिन तुलनात्मक रूप से सीधा करने के लिए अन्य प्रश्न (जो आमतौर पर रिकर्सन की आवश्यकता होती है) बनाता है। 1 99 6 में जो बैक द्वारा लिखे गए some examples in this article हैं।

0

पहले से ही question उठाया गया था।

यहाँ मेरा उत्तर (थोड़ा संपादित) है:

मुझे यकीन है कि मैं सही ढंग से अपने प्रश्न समझ में नहीं हूँ, लेकिन इस My take on trees in SQL काम कर सकता था। उस मामले में PostgreSQL - -

लिंक्ड पोस्ट डेटाबेस में पेड़ के भंडारण के वर्णित विधि लेकिन विधि काफी स्पष्ट है, तो यह किसी भी डेटाबेस के लिए आसानी से अपनाया जा सकता है।

इस विधि के साथ आप संशोधित नोड के पर सभी नोड्स को आसानी से अद्यतन कर सकते हैं, जिसमें एन सरल चयन प्रश्न हैं जहां एन रूट नोड से के की दूरी है।

शुभकामनाएं!

0

मुझे याद नहीं है कि मुझे कौन सा SO प्रश्न मिला है, लेकिन this article on sitepoint.com (दूसरा पृष्ठ) एक तालिका में पदानुक्रमित पेड़ संग्रह करने का एक और तरीका दिखाता है जो सभी बच्चे नोड्स को ढूंढना आसान बनाता है, या शीर्ष पर पथ , इस तरह बातें। उदाहरण कोड के साथ अच्छी व्याख्या।


पीएस। StackOverflow के लिए नया, उत्तर के रूप में उपरोक्त ठीक है, या यह वास्तव में प्रश्न पर एक टिप्पणी होनी चाहिए क्योंकि यह सिर्फ एक अलग समाधान के लिए एक सूचक है (वास्तव में सवाल का जवाब नहीं दे रहा है)?

संबंधित मुद्दे