Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

सर्कुलर जॉइनिंग, रिकर्सिव सर्च को रोकना

यदि आप MySQL 8.0 का उपयोग करते हैं या MariaDB 10.2 (या उच्चतर) आप पुनरावर्ती सीटीई (सामान्य तालिका भाव) को आजमा सकते हैं ।

निम्न स्कीमा और डेटा को मानते हुए:

CREATE TABLE `list_relation` (
  `child_id`  int unsigned NOT NULL,
  `parent_id` int unsigned NOT NULL,
  PRIMARY KEY (`child_id`,`parent_id`)
);
insert into list_relation (child_id, parent_id) values
    (2,1),
    (3,1),
    (4,2),
    (4,3),
    (5,3);

अब आप child_id = 1 . के साथ एक नई पंक्ति डालने का प्रयास करें और parent_id = 4 . लेकिन इससे चक्रीय संबंध बनेंगे (1->4->2->1 और 1->4->3->1 ), जिसे आप रोकना चाहते हैं। यह पता लगाने के लिए कि क्या कोई उल्टा संबंध पहले से मौजूद है, आप निम्न क्वेरी का उपयोग कर सकते हैं, जो सूची 4 के सभी माता-पिता को दिखाएगा। (विरासत में मिले/सकर्मक माता-पिता सहित):

set @new_child_id  = 1;
set @new_parent_id = 4;

with recursive rcte as (
  select *
  from list_relation r
  where r.child_id = @new_parent_id
  union all
  select r.*
  from rcte
  join list_relation r on r.child_id = rcte.parent_id
)
select * from rcte

परिणाम होगा:

child_id | parent_id
       4 |         2
       4 |         3
       2 |         1
       3 |         1

डेमो

आप परिणाम में देख सकते हैं कि सूची 1 सूची 4 . के माता-पिता में से एक है , और आप नया रिकॉर्ड नहीं डालेंगे।

चूंकि आप केवल यह जानना चाहते हैं कि क्या सूची 1 परिणाम में है, आप अंतिम पंक्ति को

. में बदल सकते हैं
select * from rcte where parent_id = @new_child_id limit 1

या करने के लिए

select exists (select * from rcte where parent_id = @new_child_id)

BTW:आप निरर्थक संबंधों को रोकने के लिए उसी क्वेरी का उपयोग कर सकते हैं। मान लें कि आप child_id = 4 के साथ रिकॉर्ड सम्मिलित करना चाहते हैं। और parent_id = 1 . यह अनावश्यक होगा, क्योंकि सूची 4 सूची 1 . को पहले से ही इनहेरिट किया गया है सूची 2 . से अधिक और सूची 3 . निम्नलिखित प्रश्न आपको दिखाएगा कि:

set @new_child_id  = 4;
set @new_parent_id = 1;

with recursive rcte as (
  select *
  from list_relation r
  where r.child_id = @new_child_id
  union all
  select r.*
  from rcte
  join list_relation r on r.child_id = rcte.parent_id
)
select exists (select * from rcte where parent_id = @new_parent_id)

और आप सभी विरासत में मिली वस्तुओं को प्राप्त करने के लिए एक समान क्वेरी का उपयोग कर सकते हैं:

set @list = 4;

with recursive rcte (list_id) as (
  select @list
  union distinct
  select r.parent_id
  from rcte
  join list_relation r on r.child_id = rcte.list_id
)
select distinct i.*
from rcte
join item i on i.list_id = rcte.list_id


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. जावा फ़ाइल MySQL पर अपलोड करें

  2. मेरे मैक पर अजगर mysqldb गलती:लाइब्रेरी लोड नहीं हुई:@ rpath/libmysqlclient.21.dylib

  3. समूहों के आधार पर mysql में पंक्तियों की गणना करें

  4. मैं तालिका में एकाधिक चेकबॉक्स मान कैसे सम्मिलित करूं?

  5. मैं विशिष्ट तिथि के लिए अद्वितीय और दोहराने वाले ग्राहक द्वारा प्रति दिन ग्राहकों की गिनती कैसे प्राप्त कर सकता हूं?