यदि आपको बस इतना ही चाहिए, तो आप LIKE खोज का उपयोग कर सकते हैं
SELECT *
FROM Table1
WHERE CELL LIKE 'AEE%';
CELL
. से शुरू होने वाले इंडेक्स के साथ यह एक रेंज चेक है, जो तेज है।
यदि आपका डेटा ऐसा नहीं दिखता है, तो आप एक path
बना सकते हैं कॉलम जो एक निर्देशिका पथ की तरह दिखता है और इसमें जड़ से तत्व तक "रास्ते/पथ पर" सभी नोड होते हैं।
| id | CELL | parent_id | path |
|====|======|===========|==========|
| 1 | A | NULL | 1/ |
| 2 | AA | 1 | 1/2/ |
| 3 | AAA | 2 | 1/2/3/ |
| 4 | AAC | 2 | 1/2/4/ |
| 5 | AB | 1 | 1/5/ |
| 6 | AE | 1 | 1/6/ |
| 7 | AEA | 6 | 1/6/7/ |
| 8 | AEE | 6 | 1/6/8/ |
| 9 | AEEB | 8 | 1/6/8/9/ |
'AE' (स्वयं सहित) के सभी वंशजों को पुनः प्राप्त करने के लिए आपकी क्वेरी होगी
SELECT *
FROM tree t
WHERE path LIKE '1/6/%';
या (MySQL विशिष्ट संयोजन)
SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = 'AE'
AND t.path LIKE CONCAT(r.path, '%');
परिणाम:
| id | CELL | parent_id | path |
|====|======|===========|==========|
| 6 | AE | 1 | 1/6/ |
| 7 | AEA | 6 | 1/6/7/ |
| 8 | AEE | 6 | 1/6/8/ |
| 9 | AEEB | 8 | 1/6/8/9/ |
प्रदर्शन
मैंने MariaDB पर नकली डेटा की 100K पंक्तियां बनाई हैं अनुक्रम प्लग इन के साथ निम्नलिखित स्क्रिप्ट का उपयोग करना:
drop table if exists tree;
CREATE TABLE tree (
`id` int primary key,
`CELL` varchar(50),
`parent_id` int,
`path` varchar(255),
unique index (`CELL`),
unique index (`path`)
);
DROP TRIGGER IF EXISTS `tree_after_insert`;
DELIMITER //
CREATE TRIGGER `tree_after_insert` BEFORE INSERT ON `tree` FOR EACH ROW BEGIN
if new.id = 1 then
set new.path := '1/';
else
set new.path := concat((
select path from tree where id = new.parent_id
), new.id, '/');
end if;
END//
DELIMITER ;
insert into tree
select seq as id
, conv(seq, 10, 36) as CELL
, case
when seq = 1 then null
else floor(rand(1) * (seq-1)) + 1
end as parent_id
, null as path
from seq_1_to_100000
;
DROP TRIGGER IF EXISTS `tree_after_insert`;
-- runtime ~ 4 sec.
परीक्षा
सभी तत्वों को रूट के अंतर्गत गिनें:
SELECT count(*)
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '1'
AND t.path LIKE CONCAT(r.path, '%');
-- result: 100000
-- runtime: ~ 30 ms
एक विशिष्ट नोड के तहत सबट्री तत्व प्राप्त करें:
SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '3B0'
AND t.path LIKE CONCAT(r.path, '%');
-- runtime: ~ 30 ms
परिणाम:
| id | CELL | parent_id | path |
|=======|======|===========|=====================================|
| 4284 | 3B0 | 614 | 1/4/11/14/614/4284/ |
| 6560 | 528 | 4284 | 1/4/11/14/614/4284/6560/ |
| 8054 | 67Q | 6560 | 1/4/11/14/614/4284/6560/8054/ |
| 14358 | B2U | 6560 | 1/4/11/14/614/4284/6560/14358/ |
| 51911 | 141Z | 4284 | 1/4/11/14/614/4284/51911/ |
| 55695 | 16Z3 | 4284 | 1/4/11/14/614/4284/55695/ |
| 80172 | 1PV0 | 8054 | 1/4/11/14/614/4284/6560/8054/80172/ |
| 87101 | 1V7H | 51911 | 1/4/11/14/614/4284/51911/87101/ |
PostgreSQL
यह PostgreSQL के लिए भी काम करता है। केवल स्ट्रिंग कॉन्सटेनेशन सिंटैक्स को बदलना होगा:
SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = 'AE'
AND t.path LIKE r.path || '%';
खोज कैसे काम करती है
यदि आप परीक्षण के उदाहरण को देखें, तो आप देखेंगे कि परिणाम में सभी पथ '1/4/11/14/614/4284/' से शुरू होते हैं। यह CELL='3B0'
. के साथ सबट्री रूट का पथ है . अगर path
कॉलम को अनुक्रमित किया गया है, इंजन उन सभी को कुशलता से ढूंढ लेगा, क्योंकि सूचकांक को path
. द्वारा क्रमबद्ध किया गया है . यह ऐसा है जैसे आप 'पोल' से शुरू होने वाले सभी शब्दों को 100K शब्दों के शब्दकोश में खोजना चाहेंगे। आपको पूरा शब्दकोश पढ़ने की आवश्यकता नहीं होगी।