मैं विस्तारित पेड़ की तरह फैशन में एक पुनरावर्ती क्वेरी के परिणामों को कैसे हल करूं?


12

मान लेते हैं कि आपके पास एक nodesटेबल है:

CREATE TABLE nodes
(
    node serial PRIMARY KEY,
    parent integer NULL REFERENCES nodes(node),
    ts timestamp NOT NULL DEFAULT now()
);

यह शीर्ष पर रूट नोड्स के साथ एक मानक नोड जैसी वृक्ष संरचना का प्रतिनिधित्व करता है और कई बच्चे नोड्स रूट नोड्स या अन्य बच्चे नोड्स से झूलते हैं।

आइए एक दो उदाहरण मान डालें:

INSERT INTO nodes (parent)
VALUES (NULL), (NULL), (NULL), (NULL), (1), (1), (1), (1), (6), (1)
     , (6), (9), (6), (6), (3), (3), (3), (15);

अब मैं पहले 10 रूट नोड्स और उनके सभी बच्चों को 4 की गहराई तक पुनः प्राप्त करना चाहता हूं:

WITH RECURSIVE node_rec AS
(
    (SELECT 1 AS depth, * FROM nodes WHERE parent IS NULL LIMIT 10)

    UNION ALL

    SELECT depth + 1, n.*
    FROM nodes AS n JOIN node_rec ON (n.parent = node_rec.node)
    WHERE depth < 4
)
SELECT * FROM node_rec;

यह बहुत अच्छा काम करता है और मुझे निम्नलिखित परिणाम देता है:

 depth | node | parent 
-------+------+--------
     1 |  1   |
     1 |  2   |
     1 |  3   |
     1 |  4   |
     2 |  5   |  1
     2 |  6   |  1
     2 |  7   |  1
     2 |  8   |  1
     2 | 10   |  1
     2 | 15   |  3
     2 | 16   |  3
     2 | 17   |  3
     3 |  9   |  6
     3 | 11   |  6
     3 | 13   |  6
     3 | 14   |  6
     3 | 18   | 15
     4 | 12   |  9

जैसा कि आपने देखा होगा, कोई ORDER BYखंड नहीं है, इसलिए आदेश परिभाषित नहीं है। आप यहाँ जो क्रम देख रहे हैं वह रूट नोड्स से लेकर गहरे नोड्स तक है।

जैसा कि आप नीचे दिए गए उदाहरण के चित्र से देख सकते हैं, मैं परिणामों को कैसे आदेश दूंगा कि वे एक विस्तारित वृक्ष दृश्य में दिखाई देंगे?

नोड्स का विस्तारित ट्री व्यू

मैं मूल रूप से चाहता हूं कि बच्चे को उनके संबंधित माता-पिता के नोड के ठीक बाद रखा जाए। यदि दो या दो से अधिक बच्चे के नोड्स में एक ही मूल नोड है, तो मैं चाहता हूं कि उन्हें उनके टाइमस्टैम्प द्वारा हल किया जाए। उपरोक्त उदाहरण के आधार पर, यहां वांछित उत्पादन क्रम है जिसे मैं प्राप्त करने की कोशिश कर रहा हूं:

 depth | node | parent | ts
-------+------+--------+---------
     1 |  1   |        | 2014-01-01 00:00:00
     2 |  5   |     1  | 2014-01-01 00:10:00
     2 |  6   |     1  | 2014-01-01 00:20:00
     3 |  9   |     6  | 2014-01-01 00:25:00
     4 |  12  |     9  | 2014-01-01 00:27:00
     3 |  11  |     6  | 2014-01-01 00:26:00
     3 |  13  |     6  | 2014-01-01 00:30:00
     3 |  14  |     6  | 2014-01-01 00:36:00
     2 |  7   |     1  | 2014-01-01 00:21:00
     2 |  8   |     1  | 2014-01-01 00:22:00
     2 |  10  |     1  | 2014-01-01 00:23:00
     1 |  2   |        | 2014-01-01 00:08:00
     1 |  3   |        | 2014-01-01 00:09:00
     2 |  15  |     3  | 2014-01-01 10:00:00
     3 |  18  |     15 | 2014-01-01 11:05:00
     2 |  16  |     3  | 2014-01-01 11:00:00
     2 |  17  |     3  | 2014-01-01 12:00:00
     1 |  4   |        | 2014-01-01 00:10:00

क्या कोई मुझे समझा सकता है कि depthकॉलम कहां से आता है? मैं इसे प्रारंभिक तालिका संरचना में नहीं देखता हूं।
सोरिन

@ सोरिन, मुझे पता है कि यह एक वास्तविक पुरानी पोस्ट है, लेकिन मैं अभी इसे Google में भर गया और सोचा कि मैं आपके प्रश्न का उत्तर दूंगा। गहराई पहली क्वेरी में शाब्दिक '1' के उपनाम से आती है।
सैम

जवाबों:


11

रूट से पत्ती तक के मार्ग का प्रतिनिधित्व करने वाला एक सरणी वांछित क्रम को प्राप्त करना चाहिए:

WITH RECURSIVE node_rec AS (
   (SELECT 1 AS depth, ARRAY[node] AS path, *
    FROM   nodes
    WHERE  parent IS NULL
    LIMIT  10
   )    
    UNION ALL
    SELECT r.depth + 1, r.path || n.node, n.*
    FROM   node_rec r 
    JOIN   nodes    n ON n.parent = r.node
    WHERE  r.depth < 4
)
SELECT *
FROM   node_rec
ORDER  BY path;

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

उस कॉलम द्वारा रूट और ऑर्डर की ओर एक-एक करके रास्ता शिफ्ट करें:

WITH RECURSIVE node_rec AS (
   (SELECT 1 AS depth, ARRAY[node] AS path, *
    FROM   nodes
    WHERE  parent IS NULL
    LIMIT  10
   )    
    UNION ALL
    SELECT r.depth + 1, r.path || n.parent, n.*
    FROM   node_rec r 
    JOIN   nodes    n ON n.parent = r.node
    WHERE  r.depth < 4
)
SELECT *
FROM   node_rec
ORDER  BY path, ts;

धन्यवाद, यह बहुत अच्छा काम करता है! हालाँकि, "अगर दो या दो से अधिक बच्चे के नोड्स में एक ही मूल नोड है, तो मैं चाहता हूं कि उन्हें उनके टाइमस्टैम्प भाग द्वारा हल किया जाए?" क्या इस दृष्टिकोण के साथ यह उल्लेखनीय है? यह हमेशा ऐसा नहीं हो सकता है कि एक उच्च नोड आईडी बाद के समय से मेल खाती है।
जॉनकंड

@ जॉनकंड: आप रूट को एक-एक करके रूट की ओर शिफ्ट कर सकते हैं (रूट नोड को पहले की स्थिति में दोहराएं!) और उस कॉलम द्वारा ऑर्डर अतिरिक्त रूप से ...
Erwin Brandstetter
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.