मुझे इसके पूर्वज से एक वंश की गहराई की गणना करने की आवश्यकता है। जब कोई रिकॉर्ड होता है object_id = parent_id = ancestor_id
, तो इसे रूट नोड (पूर्वज) माना जाता है। मैं WITH RECURSIVE
PostgreSQL 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 के परिणाम के साथ तालिका चाहते हैं ?