كيف يمكنني العثور على السجلات التي لم يتم ضمها؟

StackOverflow https://stackoverflow.com/questions/151099

  •  02-07-2019
  •  | 
  •  

سؤال

لدي جدولين متصلين ببعضهما

A لديه العديد من B

عادة كنت ستفعل:

select * from a,b where b.a_id = a.id

للحصول على كافة السجلات من a الذي يحتوي على سجل في b.

كيف يمكنني الحصول على السجلات الموجودة في "أ" فقط والتي لا تحتوي على أي شيء في "ب"؟

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

المحلول

select * from a where id not in (select a_id from b)

أو كما يقول بعض الأشخاص في هذا الموضوع:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null

نصائح أخرى

select * from a
left outer join b on a.id = b.a_id
where b.a_id is null

مقاربة أخرى:

select * from a where not exists (select * from b where b.a_id = a.id)

يعد الأسلوب "موجود" مفيدًا إذا كان هناك عبارة "حيث" أخرى تحتاج إلى إرفاقها بالاستعلام الداخلي.

SELECT id FROM a
EXCEPT
SELECT a_id FROM b;

حدد * من حيث لا يوجد معرف (اختر a_id من ب)

من المحتمل أن تحصل على أداء أفضل بكثير (من استخدام "ليس في") إذا كنت تستخدم صلة خارجية:

select * from a left outer join b on a.id = b.a_id where b.a_id is null;

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

حدد * من حيث لا يوجد معرف (اختر [معرف] من ب أين [المعرف] ليس فارغًا)

في حالة انضمام واحد، يكون الأمر سريعًا جدًا، ولكن عندما نقوم بإزالة السجلات من قاعدة البيانات التي تحتوي على حوالي 50 مليون سجل و4 انضمامات وأكثر بسبب المفاتيح الخارجية، يستغرق الأمر بضع دقائق للقيام بذلك.أسرع بكثير في الاستخدام حيث لا يكون في حالة مثل هذا:

select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)

يمكنني أيضًا أن أوصي بهذا الأسلوب للحذف في حالة عدم تكوين الحذف المتتالي.يستغرق هذا الاستعلام بضع ثوانٍ فقط.

النهج الأول هو

select a.* from a where a.id  not in (select b.ida from b)

النهج الثاني هو

select a.*
  from a left outer join b on a.id = b.ida
  where b.ida is null

النهج الأول مكلف للغاية.النهج الثاني هو الأفضل.

باستخدام PostgreSql 9.4، قمت بوظيفة "شرح الاستعلام" والاستعلام الأول كتكلفة التكلفة=0.00..1982043603.32.بدلاً من ذلك، استعلام الانضمام كتكلفة التكلفة=45946.77..45946.78

على سبيل المثال، أبحث عن جميع المنتجات غير المتوافقة مع عدم وجود مركبات.لدي 100 ألف منتج وأكثر من مليون توافق.

select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null

استغرق استعلام الانضمام حوالي 5 ثوانٍ، وبدلاً من ذلك، لم ينته إصدار الاستعلام الفرعي مطلقًا بعد 3 دقائق.

طريقة أخرى لكتابتها

select a.*
from a 
left outer join b
on a.id = b.id
where b.id is null

أوه، للضرب من قبل ناثان :)

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