मुझे इसके पूर्वज से एक वंश की गहराई की गणना करने की आवश्यकता है। जब कोई रिकॉर्ड होता है object_id = parent_id = ancestor_id, तो इसे रूट नोड (पूर्वज) माना जाता है। मैं WITH RECURSIVEPostgreSQL 9.4 के साथ एक क्वेरी चलाने की कोशिश कर रहा हूं ।
मैं डेटा या स्तंभों को नियंत्रित नहीं करता हूं। डेटा और टेबल स्कीमा एक बाहरी स्रोत से आता है। टेबल लगातार बढ़ रही है । अभी लगभग 30k रिकॉर्ड प्रति दिन है। पेड़ में कोई भी नोड गायब हो सकता है और उन्हें किसी बिंदु पर बाहरी स्रोत से खींच लिया जाएगा। वे आमतौर पर created_at DESCक्रम में खींचे जाते हैं लेकिन डेटा अतुल्यकालिक पृष्ठभूमि की नौकरियों के साथ खींचा जाता है।
शुरुआत में हमारे पास इस समस्या का एक कोड समाधान था, लेकिन अब 5M + पंक्तियों के होने में इसे पूरा होने में लगभग 30 मिनट लगते हैं।
उदाहरण तालिका की परिभाषा और परीक्षण डेटा:
CREATE TABLE objects (
id serial NOT NULL PRIMARY KEY,
customer_id integer NOT NULL,
object_id integer NOT NULL,
parent_id integer,
ancestor_id integer,
generation integer NOT NULL DEFAULT 0
);
INSERT INTO objects(id, customer_id , object_id, parent_id, ancestor_id, generation)
VALUES (2, 1, 2, 1, 1, -1), --no parent yet
(3, 2, 3, 3, 3, -1), --root node
(4, 2, 4, 3, 3, -1), --depth 1
(5, 2, 5, 4, 3, -1), --depth 2
(6, 2, 6, 5, 3, -1), --depth 3
(7, 1, 7, 7, 7, -1), --root node
(8, 1, 8, 7, 7, -1), --depth 1
(9, 1, 9, 8, 7, -1); --depth 2
ध्यान दें कि object_idअद्वितीय नहीं है, लेकिन संयोजन (customer_id, object_id)अद्वितीय है।
इस तरह एक प्रश्न चल रहा है:
WITH RECURSIVE descendants(id, customer_id, object_id, parent_id, ancestor_id, depth) AS (
SELECT id, customer_id, object_id, parent_id, ancestor_id, 0
FROM objects
WHERE object_id = parent_id
UNION
SELECT o.id, o.customer_id, o.object_id, o.parent_id, o.ancestor_id, d.depth + 1
FROM objects o
INNER JOIN descendants d ON d.parent_id = o.object_id
WHERE
d.id <> o.id
AND
d.customer_id = o.customer_id
) SELECT * FROM descendants d;
मैं चाहूंगा कि generationस्तंभ की गणना उस गहराई के रूप में की जाए जो गणना की गई थी। जब एक नया रिकॉर्ड जोड़ा जाता है, तो जेनरेशन कॉलम -1 के रूप में सेट किया जाता है। कुछ मामले ऐसे हैं, जिन्हें parent_idअभी तक नहीं खींचा जा सका है। यदि parent_idमौजूद नहीं है, तो इसे जनरेशन कॉलम को -1 पर सेट करना चाहिए।
अंतिम डेटा जैसा दिखना चाहिए:
id | customer_id | object_id | parent_id | ancestor_id | generation
2 1 2 1 1 -1
3 2 3 3 3 0
4 2 4 3 3 1
5 2 5 4 3 2
6 2 6 5 3 3
7 1 7 7 7 0
8 1 8 7 7 1
9 1 9 8 7 2
क्वेरी का परिणाम पीढ़ी कॉलम को सही गहराई से अपडेट करने के लिए होना चाहिए।
मैंने एसओ पर इस संबंधित प्रश्न के उत्तर से काम करना शुरू कर दिया ।
updateअपने पुनरावर्ती CTE के परिणाम के साथ तालिका चाहते हैं ?