سؤال

هذه هي مشكلة SQL الخاصة بي - هناك 3 طاولات:

أسماء يسرد listhasnames.معرف اسم المعرف Lists ListsID NamesID = -------- ---------------------------- 1 بول 1 كرة القدم 1 1 2 Joe 2 Basketball 1 2 3 Jenny 3 Ping Pong 2 1 4 Tina 4 Breakfast Club 2 3 5 Midnight Club Club 3 2 3 3 4 1 4 2 4 3 5 1 5 2 5 3 5 4

مما يعني أن بول (ID = 1) و Joe (ID = 2) في فريق كرة القدم (Lists.ID = 1)، بول وجيني في فريق كرة السلة، إلخ ...

الآن أحتاج إلى عبارة SQL التي ترجع القوائمs.ID بمجموعة اسم معين: في القوائم هي بولس، جو وجيني الأعضاء الوحيدين في تلك القائمة؟ الإجابة فقط lists.id = 4 (نادي الإفطار) - ولكن ليس 5 (نادي منتصف الليل) لأن تينا في تلك القائمة، أيضا.

لقد جربتها مع الانضمام الداخلي والاستفسارات الفرعية:

حدد Q1.lists_id_id من (حدد Lists_ID من الأسماء باسم T1، Listhasnames ك T2 حيث (T1.Name = 'Paul') و (T1.ID = T2.names_ID) و ((حدد العد (*) من Listhasnames كما z1 z1.lists_id_id = t2.lists_id_id) = 3) = 3) كضمان q1 Inner (حدد Lists_ID من الأسماء باسم T1، Listhasnames باسم T2 حيث (T1.Name = "Joe") و (T1.ID = T2.names_ID) و ( (حدد Count (*) من Listhasnames باسم Z1 حيث (z1.lists_id = t2.lists_lists_lists_id) = 3) as q2 على (q1.lists_id = q2.lists_id) الانضمام الداخلي (حدد lists_id من الأسماء باسم T1، listhasnames as t2 حيث (t1.name = 'jenny') و (t1.id = t2.names_id) و ((حدد العد (*) من listhasnames كما z1 حيث (z1.lists_id = t2.lists_lists_id) = 3) q3 (q1.lists_id = q3.lists_id)

تبدو معقدة بعض الشيء، أه؟ كيفية تحسين ذلك؟ أحتاج إلى ذلك فقط ListS.ID في أي أسماء محددة في (وفقط هذه الأسماء ولا أحد غيرها). ربما مع تحديد في؟

التحيات، دينيس

هل كانت مفيدة؟

المحلول

SELECT ListsId
FROM ListHasNames a
WHERE NamesId in (1, 2, 3)
AND NOT EXISTS
(SELECT * from ListHasNames b 
WHERE b.ListsId = a.ListsId 
AND b.NamesId not in (1, 2, 3))
GROUP BY ListsId
HAVING COUNT(*) = 3;

يحرر: تصحيح بفضل تعليق كريس جاو؛ التدفق ضروري لاستبعاد القوائم التي لها أشخاص آخرون عليها.تحرير 2. تصحيح اسم الجدول بفضل تعليق دينيس

نصائح أخرى

باستخدام حل Carl Manaster's كنقطة انطلاق وصلت إلى:

SELECT listsid 
FROM listhasnames 
GROUP BY listsid HAVING COUNT(*) = 3
INTERSECT
SELECT x.listsid 
FROM listhasnames x, names n 
WHERE n.name IN('Paul', 'Joe', 'Jenny') 
AND n.id = x.namesid

محدث:

select a.ListsId from
(
    --lists with three names only
    select lhn.ListsId, count(*) as count
    from ListHasNames  lhn
    inner join Names n on lhn.NamesId = n.Id 
    group by lhn.ListsId
    having count(*) = 3
) a
where a.ListsId in (select ListsId from ListHasNames lhn where NamesId = (select NamesId from names where Name = 'Paul'))
and a.ListsId in (select ListsId from ListHasNames lhn where NamesId = (select NamesId from names where Name = 'Joe'))
and a.ListsId in (select ListsId from ListHasNames lhn where NamesId = (select NamesId from names where Name = 'Jenny'))

كنت مجرد حل مشكلة مؤخرا قد تعمل بشكل جيد لحالتك أيضا. قد تكون مبالغة.

أخذت نهج إنشاء قائمة من الجمعيات المرشحة التي قد تكون الحل الصحيح، ثم استخدام مؤشر أو جدول قائمة الانتظار للذهاب إلى الحلول الصحيحة المحتملة للقيام بالتحقق الكامل.

في حالتي، تم تنفيذ ذلك من خلال القيام بذلك

select
ParentId
count(*) as ChildCount
checksum_agg(checksum(child.*) as ChildAggCrc
from parent join child on parent.parentId = child.parentId

ثم يمكنك مقارنة عدد المجموعات الاختباري والإجمالي مقابل بيانات البحث الخاصة بك (أي أسماء 3 الخاصة بك للتحقق من أجل). إذا لم تطابق أي صفوف، فأنت مضمون ليس لديك أي مباريات. إذا كان أي صف يتطابق مع ذلك، فيمكنك الدخول والقيام بانضمام لتلك Protectid المحددة للتحقق من صحة ما إذا كان هناك أي تباينات بين مجموعات الصف.

واضح وضوح الطين؟ :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top