MySQL 8+ के लिए: पुनरावर्ती साथ
का उपयोग करें
सिंटैक्स।
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))
यह रहा एक fiddle ।
यहां, @pv :='19'
. में निर्दिष्ट मान id
. पर सेट होना चाहिए माता-पिता के सभी वंशजों को आप चुनना चाहते हैं।
यह तब भी काम करेगा जब माता-पिता के पास एकाधिक हो बच्चे। हालांकि, यह आवश्यक है कि प्रत्येक रिकॉर्ड parent_id
क्वेरी के अंदर वेरिएबल असाइनमेंट
यह क्वेरी विशिष्ट MySQL सिंटैक्स का उपयोग करती है:इसके निष्पादन के दौरान चर निर्दिष्ट और संशोधित किए जाते हैं। निष्पादन के क्रम के बारे में कुछ धारणाएँ बनाई गई हैं:
- द
से
खंड का मूल्यांकन पहले किया जाता है। तो वहीं@pv
आरंभ हो जाता है। कहां
खंड का मूल्यांकन प्रत्येक रिकॉर्ड के लिएसे
. से पुनर्प्राप्ति के क्रम में किया जाता है उपनाम तो यह वह जगह है जहां एक शर्त केवल उन अभिलेखों को शामिल करने के लिए रखी जाती है जिनके लिए माता-पिता को पहले से ही वंशज पेड़ में होने के रूप में पहचाना गया था (प्राथमिक माता-पिता के सभी वंशज क्रमशः@pv
में जोड़े जाते हैं। )।- इस
कहां
में शर्तें खंड का मूल्यांकन क्रम में किया जाता है, और कुल परिणाम निश्चित होने के बाद मूल्यांकन बाधित हो जाता है। इसलिए दूसरी शर्त दूसरे स्थान पर होनी चाहिए, क्योंकि यहid
. जोड़ता है मूल सूची में, और यह केवल तभी होना चाहिए जबid
पहली शर्त पास करता है।लंबाई
फ़ंक्शन को केवल यह सुनिश्चित करने के लिए कहा जाता है कि यह स्थिति हमेशा सत्य है, भले हीpv
स्ट्रिंग किसी कारण से एक मिथ्या मान उत्पन्न करेगी।
कुल मिलाकर, किसी को भी इन धारणाओं पर भरोसा करना बहुत जोखिम भरा लग सकता है। दस्तावेज़ीकरण चेतावनी देता है:
<ब्लॉकक्वॉट>आपको अपेक्षित परिणाम मिल सकते हैं, लेकिन इसकी गारंटी नहीं है [...] उपयोगकर्ता चर वाले भावों के मूल्यांकन का क्रम अपरिभाषित है।
तो भले ही यह उपरोक्त क्वेरी के साथ लगातार काम करता है, मूल्यांकन क्रम अभी भी बदल सकता है, उदाहरण के लिए जब आप शर्तों को जोड़ते हैं या इस क्वेरी को एक बड़ी क्वेरी में एक दृश्य या उप-क्वेरी के रूप में उपयोग करते हैं। यह एक "सुविधा" है जिसे भविष्य में हटा दिया जाएगा MySQL रिलीज़ :
<ब्लॉकक्वॉट>
MySQL की पिछली रिलीज़ ने SET
. के अलावा किसी अन्य स्टेटमेंट में उपयोगकर्ता चर के लिए एक मान निर्दिष्ट करना संभव बना दिया है . यह कार्यक्षमता पश्चगामी संगतता के लिए MySQL 8.0 में समर्थित है, लेकिन MySQL के भविष्य के रिलीज में हटाने के अधीन है।
जैसा कि ऊपर बताया गया है, MySQL 8.0 से आगे आपको पुनरावर्ती साथ
का उपयोग करना चाहिए वाक्य रचना।
दक्षता
बहुत बड़े डेटा सेट के लिए यह समाधान धीमा हो सकता है, क्योंकि find_in_set
किसी सूची में किसी संख्या को खोजने के लिए ऑपरेशन सबसे आदर्श तरीका नहीं है, निश्चित रूप से उस सूची में नहीं जो परिमाण के उसी क्रम में आकार तक पहुँचती है जैसे रिकॉर्ड की संख्या वापस आती है।
वैकल्पिक 1:पुनरावर्ती के साथ
, इससे कनेक्ट करें
अधिक से अधिक डेटाबेस SQL:1999 ISO मानक [RECURSIVE] के साथ कार्यान्वित करते हैं। /कोड> वाक्य रचना
पुनरावर्ती प्रश्नों के लिए (उदा. पोस्टग्रेस 8.4+
, SQL Server 2005+
, DB2
, Oracle 11gR2+
, SQLite 3.8.4+
, Firebird 2.1+
, H2
, HyperSQL 2.1.0+
, Teradata , MariaDB 10.2.2+
) और संस्करण 8.0 के अनुसार, MySQL भी इसका समर्थन करता है
. सिंटैक्स का उपयोग करने के लिए इस उत्तर का शीर्ष देखें।
कुछ डेटाबेस में पदानुक्रमित लुक-अप के लिए एक वैकल्पिक, गैर-मानक सिंटैक्स होता है, जैसे कनेक्ट बाय
खंड Oracle
पर उपलब्ध है , DB2
, Informix , CUBRID
और अन्य डेटाबेस।
MySQL संस्करण 5.7 ऐसी सुविधा प्रदान नहीं करता है। जब आपका डेटाबेस इंजन यह सिंटैक्स प्रदान करता है या आप किसी एक में माइग्रेट कर सकते हैं, तो यह निश्चित रूप से जाने का सबसे अच्छा विकल्प है। यदि नहीं, तो निम्नलिखित विकल्पों पर भी विचार करें।
वैकल्पिक 2:पथ-शैली पहचानकर्ता
अगर आप id
असाइन करेंगे तो चीज़ें बहुत आसान हो जाती हैं मान जिनमें पदानुक्रमित जानकारी होती है:एक पथ। उदाहरण के लिए, आपके मामले में यह ऐसा दिखाई दे सकता है:
आईडी | <थ>नाम|
---|---|
19 | श्रेणी1 |
19/1 | श्रेणी2 |
19/1/1 | श्रेणी3 |
19/1/1/1 | श्रेणी4 |
फिर आपका चुनें
इस तरह दिखेगा:
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;
इसे देखें fiddle
कहां
स्थिति निर्दिष्ट करती है कि आप किस माता-पिता के वंशजों को पुनः प्राप्त करना चाहते हैं। आप इस क्वेरी को आवश्यकतानुसार अधिक स्तरों के साथ बढ़ा सकते हैं।