के लिए MySQL 8: पुनरावर्ती का उपयोग with
वाक्य रचना।
के लिए MySQL 5.x: उपयोग इनलाइन चर, पथ आईडी, या स्वयं जुड़ जाता है।
MySQL 8+
with recursive cte (id, name, parent_id) as (
select id,
name,
parent_id
from products
where parent_id = 19
union all
select p.id,
p.name,
p.parent_id
from products p
inner join cte
on p.parent_id = cte.id
)
select * from cte;
उस मान को निर्दिष्ट किया parent_id = 19
जाना चाहिए जिसे id
आप उस मूल माता-पिता के लिए सेट करना चाहते हैं जिसके सभी वंशज का चयन करना चाहते हैं।
MySQL 5.x
MySQL संस्करणों के लिए जो कॉमन टेबल एक्सप्रेशंस (संस्करण 5.7 तक) का समर्थन नहीं करते हैं, आप निम्न क्वेरी के साथ इसे प्राप्त करेंगे:
select id,
name,
parent_id
from (select * from products
order by parent_id, id) products_sorted,
(select @pv := '19') initialisation
where find_in_set(parent_id, @pv)
and length(@pv := concat(@pv, ',', id))
यहाँ एक बेला है ।
यहां, उस मान को निर्दिष्ट किया @pv := '19'
जाना चाहिए id
जिसमें उस मूल माता-पिता के लिए सेट होना चाहिए जिसे आप सभी के वंशजों का चयन करना चाहते हैं।
यह तब भी काम करेगा जब एक अभिभावक के कई बच्चे होंगे। हालांकि, यह आवश्यक है कि प्रत्येक रिकॉर्ड शर्त को पूरा करे parent_id < id
, अन्यथा परिणाम पूर्ण नहीं होंगे।
एक क्वेरी के अंदर परिवर्तनीय कार्य
यह क्वेरी विशिष्ट MySQL सिंटैक्स का उपयोग करती है: चर इसके निष्पादन के दौरान निर्दिष्ट और संशोधित किए जाते हैं। निष्पादन के आदेश के बारे में कुछ धारणाएँ बनाई गई हैं:
from
खंड प्रथम मूल्यांकन किया जाता है। तो यह वह जगह है जहाँ @pv
से आरंभ होता है।
where
खंड से पुनः प्राप्ति के क्रम में प्रत्येक रिकॉर्ड के लिए मूल्यांकन किया जाता है from
उपनाम। तो यह वह जगह है जहां केवल उन अभिलेखों को शामिल किया जाता है जिनके लिए माता-पिता को पहले से ही वंशज वृक्ष के रूप में पहचाना जाता था (प्राथमिक माता-पिता के सभी वंशज उत्तरोत्तर जोड़े जाते हैं @pv
)।
- इस
where
खंड में शर्तों का मूल्यांकन क्रम में किया जाता है, और कुल परिणाम निश्चित होने के बाद मूल्यांकन बाधित होता है। इसलिए दूसरी स्थिति दूसरे स्थान पर होनी चाहिए, क्योंकि यह id
मूल सूची में जुड़ जाती है, और यह केवल तभी होना चाहिए id
जब पहली शर्त पास हो जाए । length
समारोह केवल बनाने के लिए कहा जाता है यकीन है कि इस हालत हमेशा की तरह, सही है भले ही pv
स्ट्रिंग किसी कारण के लिए एक falsy मूल्य प्राप्त करेगी।
सभी के सभी, इन मान्यताओं पर भरोसा करने के लिए बहुत जोखिम भरा हो सकता है। प्रलेखन चेतावनी देते हैं:
आपको वे परिणाम मिल सकते हैं जिनकी आप अपेक्षा करते हैं, लेकिन यह गारंटी नहीं है [...] उपयोगकर्ता चर शामिल अभिव्यक्तियों के लिए मूल्यांकन का क्रम अपरिभाषित है।
इसलिए भले ही यह उपरोक्त क्वेरी के साथ लगातार काम करता हो, मूल्यांकन आदेश अभी भी बदल सकता है, उदाहरण के लिए, जब आप शर्तों को जोड़ते हैं या इस क्वेरी को एक बड़े क्वेरी में दृश्य या उप-क्वेरी के रूप में उपयोग करते हैं। यह एक "फीचर" है जिसे भविष्य के MySQL रिलीज में हटा दिया जाएगा :
MySQL के पिछले रिलीज ने इसके अलावा अन्य बयानों में एक उपयोगकर्ता चर के लिए एक मूल्य प्रदान करना संभव बना दिया SET
। यह कार्यक्षमता बैकवर्ड संगतता के लिए MySQL 8.0 में समर्थित है, लेकिन MySQL के भविष्य के रिलीज में हटाने के अधीन है।
जैसा कि ऊपर कहा गया है, MySQL 8.0 पर आपको पुनरावर्ती with
सिंटैक्स का उपयोग करना चाहिए ।
दक्षता
बहुत बड़े डेटा सेटों के लिए यह समाधान धीमा हो सकता है, क्योंकि find_in_set
ऑपरेशन किसी सूची में नंबर खोजने के लिए सबसे आदर्श तरीका नहीं है, निश्चित रूप से उस सूची में नहीं जो परिमाण के समान क्रम में एक आकार तक पहुंचता है क्योंकि रिकॉर्ड की संख्या वापस आ गई।
विकल्प 1: with recursive
,connect by
अधिक से अधिक डेटाबेस SQL कोWITH [RECURSIVE]
लागू करते हैं : पुनरावर्ती प्रश्नों के लिए 1999 आईएसओ मानक वाक्यविन्यास (जैसे Postgres 8.4+ , SQL Server 2005+ , DB2 , Oracle 11gR2 + , SQLite 3.8.4+ , Firebird 2.1+ , H2 , HyperSQL 2.1.0+ , Teradata) , मारियाबीडी 10.2.2+ )। और संस्करण 8.0 के रूप में , MySQL भी इसका समर्थन करता है । सिंटैक्स का उपयोग करने के लिए इस उत्तर के शीर्ष पर देखें।
कुछ डेटाबेस में पदानुक्रमिक लुक-अप के लिए एक वैकल्पिक, गैर-मानक वाक्यविन्यास है, जैसे कि Oracle , DB2 , Informix , CUBRID और अन्य डेटाबेस CONNECT BY
पर उपलब्ध खंड ।
MySQL संस्करण 5.7 इस तरह की सुविधा प्रदान नहीं करता है। जब आपका डेटाबेस इंजन इस सिंटैक्स को प्रदान करता है या आप उस एक को माइग्रेट कर सकते हैं, जो निश्चित रूप से सबसे अच्छा विकल्प है। यदि नहीं, तो निम्नलिखित विकल्पों पर भी विचार करें।
वैकल्पिक 2: पथ-शैली पहचानकर्ता
चीजें बहुत आसान हो जाती हैं यदि आप उन id
मानों को असाइन करेंगे जिनमें पदानुक्रमित जानकारी है: एक पथ। उदाहरण के लिए, आपके मामले में यह इस तरह दिख सकता है:
ID | NAME
19 | category1
19/1 | category2
19/1/1 | category3
19/1/1/1 | category4
तब आपका मन select
ऐसा लगेगा:
select id,
name
from products
where id like '19/%'
वैकल्पिक 3: बार-बार स्व-जुड़ना
यदि आपको पता है कि आपका पदानुक्रम वृक्ष कितना गहरा हो सकता है, तो आप इसके लिए एक मानक सीमा का उपयोग कर सकते हैं sql
:
select p6.parent_id as parent6_id,
p5.parent_id as parent5_id,
p4.parent_id as parent4_id,
p3.parent_id as parent3_id,
p2.parent_id as parent2_id,
p1.parent_id as parent_id,
p1.id as product_id,
p1.name
from products p1
left join products p2 on p2.id = p1.parent_id
left join products p3 on p3.id = p2.parent_id
left join products p4 on p4.id = p3.parent_id
left join products p5 on p5.id = p4.parent_id
left join products p6 on p6.id = p5.parent_id
where 19 in (p1.parent_id,
p2.parent_id,
p3.parent_id,
p4.parent_id,
p5.parent_id,
p6.parent_id)
order by 1, 2, 3, 4, 5, 6, 7;
देखिए यह फील
यह where
शर्त निर्दिष्ट करती है कि आप किस माता-पिता के वंशज को पुनः प्राप्त करना चाहते हैं। आप आवश्यकतानुसार इस स्तर को और बढ़ा सकते हैं।