sql एसक्यूएल कैसे कई रिश्ते के लिए कई खोज करने के लिए




search many-to-many (6)

नोट: मैंने वास्तव में इसका परीक्षण नहीं किया है। यह भी मान लिया गया है कि आपके पास नोट-लबेल नामक कई-से-कई टेबल हैं, जो बिल्कुल भी मामला न हो।

यदि आप बस किसी भी लेबल वाले नोट्स चाहते हैं, तो ऐसा कुछ ऐसा हो सकता है

SELECT DISTINCT n.id, n.text
FROM notes n
INNER JOIN notes_labels nl ON n.id = nl.note_id
INNER JOIN labels l ON nl.label_id = l.id
WHERE l.label IN (?, ?)

यदि आप सभी लेबल्स के नोट्स चाहते हैं, तो थोड़ा अतिरिक्त काम है

SELECT n.id, n.text
FROM notes n
INNER JOIN notes_labels nl ON n.id = nl.note_id
INNER JOIN labels l ON nl.label_id = l.id
WHERE l.label IN (?, ?)
GROUP BY n.id, n.text
HAVING COUNT(*) = 2;

? एक एसक्यूएल प्लेसहोल्डर है और 2 आपके द्वारा खोजे जाने वाले टैग की संख्या है। यह मान रहा है कि लिंक तालिका में दोनों आईडी कॉलम एक मिश्रित प्राथमिक कुंजी के रूप में है।

मेरे पास दो मुख्य टेबल notes और labels साथ एक डेटाबेस है उनके पास कई-से-कई रिश्ते हैं (जैसे स्टैकेवरफ्लो डॉटकॉम के लेबल के साथ प्रश्न हैं)। मैं क्या सोच रहा हूं, मैं एसक्यूएल का इस्तेमाल करते हुए कई लेबलों का उपयोग कर एक नोट कैसे खोज सकता हूं?

उदाहरण के लिए अगर मेरे पास तीन लेबल "एक", "दो" और "तीन" के साथ एक नोट "टेस्ट" है और मेरे पास एक दूसरा नोट "test2" है जिसमें लेबल "एक" और "दो" एसक्यूएल क्वेरी क्या है लेबल्स "एक" और "दो" के साथ जुड़े सभी नोट मिल जाए?


आप इस बारे में कुछ नहीं कहते हैं कि यह कैसे कई-से-कई रिश्ते हैं। मुझे लगता है कि लेबल तालिका में लेबल्स (नोटिड: इंट, लेबल: वर्चार) है - प्राथमिक कुंजी के साथ दोनों में फैले?

SELECT DISTINCT n.id from notes as n, notes_labels as nl WHERE n.id = nl.noteid AND nl.text in (label1, label2);

अपने कॉलम नामों के साथ बदलें, और लेबल के लिए उचित प्लेसहोल्डर डालें


यदि आपको सिर्फ एक सूची की आवश्यकता है, तो आप दोहराव से बचने के लिए where exists उपयोग कर सकते हैं। यदि आपके चयन मानदंड में नोड के खिलाफ कई टैग हैं तो आपको परिणाम में डुप्लिकेट पंक्तियां मिलेंगी। यहां where exists एक उदाहरण where exists :

create table notes (
       NoteID int not null primary key
      ,NoteText varchar (max)
)
go

create table tags (
       TagID int not null primary key
      ,TagText varchar (100)
)
go

create table note_tag (
       NoteID int not null
      ,TagID int not null
)
go

alter table note_tag
  add constraint PK_NoteTag
      primary key clustered (TagID, NoteID)
go

insert notes values (1, 'Note A')
insert notes values (2, 'Note B')
insert notes values (3, 'Note C')

insert tags values (1, 'Tag1')
insert tags values (2, 'Tag2')
insert tags values (3, 'Tag3')

insert note_tag values (1, 1) -- Note A, Tag1
insert note_tag values (1, 2) -- Note A, Tag2
insert note_tag values (2, 2) -- Note B, Tag2
insert note_tag values (3, 1) -- Note C, Tag1
insert note_tag values (3, 3) -- Note C, Tag3
go

select n.NoteID
      ,n.NoteText
  from notes n
 where exists
       (select 1
          from note_tag nt
          join tags t
            on t.TagID = nt.TagID
         where n.NoteID = nt.NoteID
           and t.TagText in ('Tag1', 'Tag3'))


NoteID      NoteText
----------- ----------------
1           Note A
3           Note C

मान लें कि आपके पास सामान्यीकृत डाटाबेस है, notes और labels बीच आपके पास एक अन्य तालिका होना चाहिए

आपको तब तालिकाओं में शामिल inner join लिए एक inner join का उपयोग करना चाहिए

  1. बाइंड टेबल के साथ labels तालिका में शामिल हों (बहुत-से-कई टेबल)
  2. पिछली क्वेरी के साथ notes तालिका में शामिल हों

उदाहरण:

select * from ((labels l inner join labels_notes ln on l.labelid = ln.labelid) inner join notes n on ln.notesid = n.noteid)

इस तरह, आपने दोनों तालिकाओं को एक साथ जोड़ दिया है।

अब आपको जो कुछ जोड़ने की जरूरत है वह where है ... लेकिन मैं इसे आपके ऊपर छोड़ दूँगा


उन नोटों का विवरण प्राप्त करने के लिए जिनके लेबल 'वन' और 'दो' हैं:

select * from notes
where note_id in
( select note_id from labels where label = 'One'
  intersect
  select note_id from labels where label = 'Two'
)

select * from notes a
inner join notes_labels mm on (mm.note = a.id and mm.labeltext in ('one', 'two') )

बेशक, अपने वास्तविक स्तंभ नामों के साथ बदलें, उम्मीद है कि आपकी तालिका के बारे में मेरी मान्यताओं सही थीं।

और वास्तव में आपके प्रश्न में संभवतः अस्पष्टता का थोड़ा सा अंग्रेजी के लिए धन्यवाद है और शब्द और कभी-कभी कैसे उपयोग किया जाता है। यदि आप का मतलब है कि आप देखना चाहते हैं, उदाहरण के लिए, एक नोट 'एक' पर टैग किया गया है, लेकिन 'दो' नहीं है, यह काम करना चाहिए (अपने 'और' का मतलब करने के लिए, 'मुझे लेबल के साथ सभी नोट' एक 'और / अधिक सभी को दिखाएं लेबल 'दो' के साथ नोट) हालांकि, यदि आप केवल नोट्स चाहते हैं जो दोनों लेबल हैं, तो यह इसके बारे में जाने का एक तरीका होगा:

select * from notes a
where exists (select 1 from notes_labels b where b.note = a.id and b.labeltext = 'one')
     and exists (select 1 from notes_labels c where c.note = a.id and c.labeltext = 'two')

संपादित करें: सभी सुझावों के लिए धन्यवाद, मेरे दिमाग में सोमवार गियर थोड़ी धीमी गति से दिखता है ... ऐसा लगता है कि मुझे इसे विकी होना चाहिए था!





relational-division