MySQL: ट्री-पदानुक्रमित क्वेरी


20

माय-एसक्यूएल में एक ट्रे के साथ सब-ट्रे

मेरे MYSQL में Database COMPANY, मैं एक Table: Employeeपुनरावर्ती संघ के साथ हूं , एक कर्मचारी दूसरे कर्मचारी का मालिक हो सकता है। A self relationship of kind (SuperVisor (1)- SuperVisee (∞) )

तालिका बनाने की क्वेरी:

CREATE TABLE IF NOT EXISTS `Employee` (
  `SSN` varchar(64) NOT NULL,
  `Name` varchar(64) DEFAULT NULL,
  `Designation` varchar(128) NOT NULL,
  `MSSN` varchar(64) NOT NULL, 
  PRIMARY KEY (`SSN`),
  CONSTRAINT `FK_Manager_Employee`  
              FOREIGN KEY (`MSSN`) REFERENCES Employee(SSN)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

मैंने टुपल्स (क्वेरी) का एक सेट डाला है:

INSERT INTO Employee VALUES 
 ("1", "A", "OWNER",  "1"),  

 ("2", "B", "BOSS",   "1"), # Employees under OWNER 
 ("3", "F", "BOSS",   "1"),

 ("4", "C", "BOSS",   "2"), # Employees under B
 ("5", "H", "BOSS",   "2"), 
 ("6", "L", "WORKER", "2"), 
 ("7", "I", "BOSS",   "2"), 
 # Remaining Leaf nodes   
 ("8", "K", "WORKER", "3"), # Employee under F     

 ("9", "J", "WORKER", "7"), # Employee under I     

 ("10","G", "WORKER", "5"), # Employee under H

 ("11","D", "WORKER", "4"), # Employee under C
 ("12","E", "WORKER", "4")  

सम्मिलित पंक्तियों में ट्री-हायरार्किकल-रिलेशनशिप निम्नलिखित है :

         A     <---ROOT-OWNER
        /|\             
       / A \        
      B     F 
    //| \    \          
   // |  \    K     
  / | |   \                     
 I  L H    C        
/     |   / \ 
J     G  D   E

मैंने संबंध खोजने के लिए एक प्रश्न लिखा:

SELECT  SUPERVISOR.name AS SuperVisor, 
        GROUP_CONCAT(SUPERVISEE.name  ORDER BY SUPERVISEE.name ) AS SuperVisee, 
        COUNT(*)  
FROM Employee AS SUPERVISOR 
  INNER JOIN Employee SUPERVISEE ON  SUPERVISOR.SSN = SUPERVISEE.MSSN 
GROUP BY SuperVisor;

और आउटपुट है:

+------------+------------+----------+
| SuperVisor | SuperVisee | COUNT(*) |
+------------+------------+----------+
| A          | A,B,F      |        3 |
| B          | C,H,I,L    |        4 |
| C          | D,E        |        2 |
| F          | K          |        1 |
| H          | G          |        1 |
| I          | J          |        1 |
+------------+------------+----------+
6 rows in set (0.00 sec)

[ प्रश्न ]
पूरा पदानुक्रमित पेड़ के बजाय, मुझे SUB-TREEएक बिंदु (चयनात्मक) उदाहरण से चाहिए:
यदि इनपुट तर्क है Bतो आउटपुट नीचे के रूप में होना चाहिए ...

+------------+------------+----------+
| SuperVisor | SuperVisee | COUNT(*) |
+------------+------------+----------+
| B          | C,H,I,L    |        4 |
| C          | D,E        |        2 |
| H          | G          |        1 |
| I          | J          |        1 |
+------------+------------+----------+   

कृपया इस पर मेरी सहायता करें। यदि क्वेरी नहीं है, तो संग्रहीत कार्यविधि मददगार हो सकती है।
मैंने कोशिश की, लेकिन सभी प्रयास बेकार थे!



मैंने इस प्रश्न का अधिक आसानी से पता लगाने में उपयोग करने के लिए समुदाय के लिए एक परीक्षण ढांचा प्रदान किया।
मेलमोकब

@bluefeet हां, एक बार मुझे जवाब मिल जाएगा तो मैं इन दोनों में से एक को हटा दूंगा।
बृजेश चौहान

1
@GrijeshChauhan मुझे आपसे यह पूछना चाहिए: अपनी खुद की दृश्यमान तरंगें बनाना बेहतर है? कंकड़ को समुद्र में फेंकने के लिए, या चट्टानों को एक छोटे तालाब में फेंकने के लिए? विशेषज्ञों के लिए सीधे जाना लगभग निश्चित रूप से आपको सबसे अच्छा जवाब देने वाला है, और इस तरह का प्रश्न इतना महत्वपूर्ण (उन्नत डेटाबेस विषय) है कि हमने इसे नेटवर्क पर अपनी खुद की साइट दी है। लेकिन मैं आपको यह पूछने से नहीं रोकूंगा कि आपको यह पसंद नहीं है, यह आपका विशेषाधिकार है। मेरा अभिप्राय यह है कि यदि मुझे लगता है कि वह जहां है, उसे दूसरी साइट पर ले जाने के लिए मतदान करना है। : डी हम दोनों का उपयोग नेटवर्क के रूप में हम इस मामले में उचित समझें: डी
jcolebrand

1
@jcolebrand: वास्तव में यह केवल मेरी गलती थी। मैं एक बेहतर, त्वरित और कई प्रतिक्रिया प्राप्त करने के लिए कई पक्षों पर प्रश्न पोस्ट करने के लिए उपयोग करता हूं। It my experience मुझे हमेशा विशेषज्ञ पक्षों से बेहतर जवाब मिला । और मुझे लगता है कि डेटाबेस एडमिनिस्ट्रेटर से सवाल पूछना बेहतर था। सभी मामलों में, मैं स्टैकओवरफ्लो और लोगों के लिए बहुत आभारी हूं जो यहां सक्रिय हैं। मुझे वास्तव में बहुत सी समस्या का समाधान मिला जो मुझे या किसी अन्य वेब को खोजने के लिए बहुत कठिन था।
बृजेश चौहान

जवाबों:


5

मैंने पहले ही इस प्रकृति के कुछ को संग्रहीत प्रक्रियाओं का उपयोग करके संबोधित किया: एक पदानुक्रमित क्षेत्र का उच्चतम स्तर खोजें: बनाम बिना सीटीई के (अक्टूबर 24, 2011)

यदि आप मेरी पोस्ट को देखते हैं, तो आप किसी भी बिंदु से पेड़ को पीछे हटाने के लिए एक मॉडल के रूप में गेटएनेट्री और गेटफैमिली कार्यों का उपयोग कर सकते हैं।

UPDATE 2012-12-11 12:11 EDT

मैंने अपने कोड से अपने कोड को वापस देखा । मैंने आपके लिए संग्रहीत कार्य को लिखा:

DELIMITER $$

DROP FUNCTION IF EXISTS `cte_test`.`GetFamilyTree` $$
CREATE FUNCTION `cte_test`.`GetFamilyTree`(GivenName varchar(64))
RETURNS varchar(1024) CHARSET latin1
DETERMINISTIC
BEGIN

    DECLARE rv,q,queue,queue_children,queue_names VARCHAR(1024);
    DECLARE queue_length,pos INT;
    DECLARE GivenSSN,front_ssn VARCHAR(64);

    SET rv = '';

    SELECT SSN INTO GivenSSN
    FROM Employee
    WHERE name = GivenName
    AND Designation <> 'OWNER';
    IF ISNULL(GivenSSN) THEN
        RETURN ev;
    END IF;

    SET queue = GivenSSN;
    SET queue_length = 1;

    WHILE queue_length > 0 DO
        IF queue_length = 1 THEN
            SET front_ssn = queue;
            SET queue = '';
        ELSE
            SET pos = LOCATE(',',queue);
            SET front_ssn = LEFT(queue,pos - 1);
            SET q = SUBSTR(queue,pos + 1);
            SET queue = q;
        END IF;
        SET queue_length = queue_length - 1;
        SELECT IFNULL(qc,'') INTO queue_children
        FROM
        (
            SELECT GROUP_CONCAT(SSN) qc FROM Employee
            WHERE MSSN = front_ssn AND Designation <> 'OWNER'
        ) A;
        SELECT IFNULL(qc,'') INTO queue_names
        FROM
        (
            SELECT GROUP_CONCAT(name) qc FROM Employee
            WHERE MSSN = front_ssn AND Designation <> 'OWNER'
        ) A;
        IF LENGTH(queue_children) = 0 THEN
            IF LENGTH(queue) = 0 THEN
                SET queue_length = 0;
            END IF;
        ELSE
            IF LENGTH(rv) = 0 THEN
                SET rv = queue_names;
            ELSE
                SET rv = CONCAT(rv,',',queue_names);
            END IF;
            IF LENGTH(queue) = 0 THEN
                SET queue = queue_children;
            ELSE
                SET queue = CONCAT(queue,',',queue_children);
            END IF;
            SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
        END IF;
    END WHILE;

    RETURN rv;

END $$

यह वास्तव में काम करता है। यहाँ एक नमूना है:

mysql> SELECT name,GetFamilyTree(name) FamilyTree
    -> FROM Employee WHERE Designation <> 'OWNER';
+------+-----------------------+
| name | FamilyTree            |
+------+-----------------------+
| A    | B,F,C,H,L,I,K,D,E,G,J |
| G    |                       |
| D    |                       |
| E    |                       |
| B    | C,H,L,I,D,E,G,J       |
| F    | K                     |
| C    | D,E                   |
| H    | G                     |
| L    |                       |
| I    | J                     |
| K    |                       |
| J    |                       |
+------+-----------------------+
12 rows in set (0.36 sec)

mysql>

केवल एक कैच है। मैंने मालिक के लिए एक अतिरिक्त पंक्ति जोड़ी

  • स्वामी के पास SSN 0 है
  • मालिक MSSN 0 के साथ उसका अपना मालिक है

यहाँ डेटा है

mysql> select * from Employee;
+-----+------+-------------+------+
| SSN | Name | Designation | MSSN |
+-----+------+-------------+------+
| 0   | A    | OWNER       | 0    |
| 1   | A    | BOSS        | 0    |
| 10  | G    | WORKER      | 5    |
| 11  | D    | WORKER      | 4    |
| 12  | E    | WORKER      | 4    |
| 2   | B    | BOSS        | 1    |
| 3   | F    | BOSS        | 1    |
| 4   | C    | BOSS        | 2    |
| 5   | H    | BOSS        | 2    |
| 6   | L    | WORKER      | 2    |
| 7   | I    | BOSS        | 2    |
| 8   | K    | WORKER      | 3    |
| 9   | J    | WORKER      | 7    |
+-----+------+-------------+------+
13 rows in set (0.00 sec)

mysql>

समझ में आया!
बृजेश चौहान

मैं Aइस तरह के सभी वंशजों को प्राप्त करने के लिए कैसे अनुकूलित कर सकता हूंA A/B A/B/C A/B/C/D A/B/C/E A/B/H A/B/H/G A/B/I A/B/I/J A/B/L A/F A/F/K
स्मिथ

क्या यह बहुसंख्या को भी संभालता है? जैसा कि यह मेरे डेटाबेस में लटका हुआ है, जहां एक माता-पिता के कई नोड मिले
عثمان hangingني

3

आप जो उपयोग कर रहे हैं उसे एडिक्शन लिस्ट मॉडल कहा जाता है । इसकी बहुत सी सीमाएँ हैं। जब आप किसी विशिष्ट स्थान पर नोड को हटाना / सम्मिलित करना चाहते हैं तो आपको समस्या होगी। इसके बेहतर आप नेस्टेड सेट मॉडल का उपयोग करें

इसकी विस्तृत व्याख्या है । दुर्भाग्य से mysql.com पर लेख मौजूद नहीं है।


5
" इसकी बहुत सी सीमाएँ हैं " - लेकिन केवल MySQL का उपयोग करते समय। लगभग सभी DBMS पुनरावर्ती प्रश्नों का समर्थन करते हैं (MySQL बहुत कम में से एक है जो ऐसा नहीं करता है) और इससे मॉडल को वास्तव में आसानी से निपटना आसान हो जाता है।
a_horse_with_no_name

@a_horse_with_no_name ने MySQL के अलावा कभी भी कुछ भी इस्तेमाल नहीं किया। इसलिए मैं इसे कभी नहीं जान पाया। सूचना के लिए धन्यवाद।
शिप्लू मोकादिम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.