سؤال

تخيل الجداول التالية:

إنشاء مربعات الجدول (معرف int ، نص الاسم ، ...) ؛

قم بإنشاء Table ThingsInboxes (ID int ، box_id int ، thing enum ('Apple ،' Banana '،' Orange ') ؛

والجداول تبدو مثل:

Boxes:
id | name
1  | orangesOnly
2  | orangesOnly2
3  | orangesBananas
4  | misc

thingsinboxes:
id | box_id | thing
1  |  1     | orange
2  |  1     | orange
3  |  2     | orange
4  |  3     | orange
5  |  3     | banana
6  |  4     | orange
7  |  4     | apple
8  |  4     | banana

كيف يمكنني اختيار الصناديق التي تحتوي على برتقالي واحد على الأقل ولا شيء ليس برتقاليًا؟

كيف هذا النطاق ، على افتراض أن لدي عدة مئات من الآلاف من الصناديق وربما مليون شيء في الصناديق؟

أرغب في الحفاظ على كل هذا في SQL إن أمكن ، بدلاً من معالجة ما بعد المعالجة.

أنا أستخدم كل من Postgres و MySQL ، لذلك من المحتمل أن تكون الفخات الفرعية سيئة ، بالنظر إلى أن MySQL لا يحسن الفوز الفرعي (Pre Pred 6 ، على أي حال).

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

المحلول

SELECT b.*
FROM boxes b JOIN thingsinboxes t ON (b.id = t.box_id)
GROUP BY b.id
HAVING COUNT(DISTINCT t.thing) = 1 AND SUM(t.thing = 'orange') > 0;

إليك حل آخر لا يستخدم المجموعة بواسطة:

SELECT DISTINCT b.*
FROM boxes b
  JOIN thingsinboxes t1 
    ON (b.id = t1.box_id AND t1.thing = 'orange')
  LEFT OUTER JOIN thingsinboxes t2 
    ON (b.id = t2.box_id AND t2.thing != 'orange')
WHERE t2.box_id IS NULL;

كما هو الحال دائمًا ، قبل إجراء استنتاجات حول قابلية التوسع أو أداء الاستعلام ، عليك أن تجربها مع مجموعة بيانات واقعية ، وقياس الأداء.

نصائح أخرى

أعتقد أن استعلام بيل كاروين على ما يرام ، ولكن إذا كانت نسبة صغيرة نسبيًا من الصناديق تحتوي على برتقال ، فيجب أن تكون قادرًا على تسريع الأمور باستخدام فهرس على thing مجال:

SELECT b.*
FROM boxes b JOIN thingsinboxes t1 ON (b.id = t1.box_id)
WHERE t1.thing = 'orange'
AND NOT EXISTS (
    SELECT 1
    FROM thingsinboxes t2
    WHERE t2.box_id = b.id
    AND t2.thing <> 'orange'
)
GROUP BY t1.box_id

ال WHERE NOT EXISTS لن يتم تشغيل الاسعة الفرعي إلا مرة واحدة لكل شيء برتقالي ، لذلك ليس مكلفًا للغاية بشرط ألا يكون هناك العديد من البرتقال.

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