0Pricing
SQL Interview Prep · درس

العثور على الصفوف دون تطابق (Anti-Join)

نمط LEFT JOIN / IS NULL للعثور على السجلات孤 والمفقودة

العثور على الصفوف دون تطابق (Anti-Join) درس مجاني في SQL Interview Prep على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.

سؤال Anti-Join

من أكثر أسئلة outer join شيوعًا: «اعثروا على العملاء الذين لم يضعوا أي طلب من قبل.» أو: «اعرضوا المنتجات التي لم تُبع قط»، أو «الطلبات التي لا يطابقها أي عميل.»

تشترك هذه الأسئلة جميعًا في بنية واحدة: صفوف في جدول لا تطابقها صفوف في جدول آخر. والأسلوب الاصطلاحي الواضح هو anti-join، الذي يُبنى باستخدام LEFT JOIN مع عامل تصفية IS NULL.

الفكرة الأساسية

ابدؤوا باستخدام LEFT JOIN؛ فهو يحتفظ بكل صف أيسر، وتُسند إلى صفوف الجهة اليسرى غير المتطابقة قيمة NULL في أعمدة الجدول الأيمن.

لذلك تكون الصفوف غير المتطابقة بالضبط هي الصفوف التي تكون فيها قيمة أحد أعمدة الجدول الأيمن NULL. صفّوا وفق هذا الشرط، وستعزلون صفوف عدم التطابق. هذه هي الحيلة كاملة.

بناء النمط

إليكم anti-join الاصطلاحي للعثور على العملاء الذين ليس لديهم طلبات. اقرأوه على مرحلتين: يحافظ LEFT JOIN على جميع العملاء، ثم يحتفظ WHERE o.customer_id IS NULL بغير المتطابقين فقط.

SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
WHERE o.customer_id IS NULL;
-- only customers with zero orders

لماذا ينجح هذا خطوة بخطوة

تتبّعوا العملية باستخدام بياناتنا، حيث لا تملك Carol أي طلبات:

  • ينتج LEFT JOIN صفوف Alice (مرتين)، وBob (مرة واحدة)، وCarol مع قيم NULL في أعمدة الجهة اليمنى.
  • يتخلص WHERE o.customer_id IS NULL من Alice وBob (إذ تحتوي أعمدتهما في الجهة اليمنى على قيم فعلية).
  • لا يبقى سوى صف Carol، وهو الصف الذي أُنشئت قيم الجهة اليمنى فيه على هيئة NULL.

يُنفّذ عامل التصفية بعد JOIN، ولذلك يرى قيم NULL هذه ويختار الأيتام تحديدًا.

اختيار العمود الصحيح لاختباره

اختبروا عمودًا من الجدول الأيمن لا يمكن أن تكون قيمته NULL بشكل مشروع أبدًا عند وجود تطابق فعلي، ويفضّل أن يكون مفتاح JOIN أو المفتاح الأساسي.

إذا اختبرتم عمودًا يقبل NULL في الجهة اليمنى مثل o.shipped_at، فستلتقطون أيضًا الطلبات الموجودة التي لم تُشحن بعد، وهذا جواب خاطئ. أما اختبار o.customer_id (مفتاح JOIN) أو o.id (مفتاحه الأساسي) فيضمن أن تعني قيمة NULL عدم تطابق أي صف.

-- SAFE: join key / primary key
WHERE o.id IS NULL

-- RISKY: a nullable data column
WHERE o.shipped_at IS NULL  -- catches unshipped too!

Anti-Join في مقابل NOT IN

يقارن المحاوِرون بين anti-join وNOT IN. فهما يبدوان متكافئين، لكنهما يختلفان عند التعامل مع NULL.

إذا أعاد الاستعلام الفرعي قيمة NULL واحدة على الأقل، فلن يعيد NOT IN أي صف على الإطلاق، وهذا خطأ صامت سيئ السمعة. أما anti-join باستخدام LEFT JOIN / IS NULL فلا يتأثر بذلك.

-- DANGEROUS if any customer_id is NULL
SELECT id, name FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);

-- SAFE anti-join, same intent
SELECT c.id, c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

Anti-Join في مقابل NOT EXISTS

البديل المكافئ الآخر هو NOT EXISTS مع استعلام فرعي مرتبط. وهو يتعامل مع NULL بشكل صحيح أيضًا، وغالبًا ما يكون بالسرعة نفسها.

يمكن للطرق الثلاث (LEFT JOIN/IS NULL وNOT EXISTS وNOT IN) التعبير عن anti-join، لكن في المقابلة يُفضّل استخدام LEFT JOIN/IS NULL أو NOT EXISTS لسلامتهما عند التعامل مع NULL. والإشارة إلى مشكلة NOT IN مع NULL تمنحكم نقاطًا إضافية.

SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.id
);

خطأ شائع

من الأخطاء المتكررة وضع شرط عدم التطابق في عبارة ON بدلًا من WHERE.

إن كتابة ... ON o.customer_id = c.id AND o.id IS NULL لا تؤدي إلى تصفية النتيجة؛ بل تغيّر فقط ما يُعد تطابقًا، ويظل كل عميل موجودًا في نتيجة LEFT JOIN. يجب أن يكون اختبار IS NULL في WHERE، ليُطبّق بعد JOIN. وسنغطي هذا الفخ بالتفصيل في الدرس التالي.

العثور على صفوف فرعية يتيمة

يعمل هذا النمط في الاتجاه الآخر أيضًا. للعثور على الطلبات التي تشير إلى عميل مفقود (أي الصفوف اليتيمة، ضمن فحص سلامة البيانات)، حافظوا على orders واختبروا جانب العملاء بحثًا عن NULL.

SELECT o.id AS order_id, o.customer_id
FROM orders o
LEFT JOIN customers c
  ON c.id = o.customer_id
WHERE c.id IS NULL;
-- orders pointing to a non-existent customer

حساب الصفوف اليتيمة

غالبًا ما يكون المطلوب مجرد عدد: «كم عدد العملاء الذين لم يطلبوا شيئًا من قبل؟» يمكنكم تغليف anti-join أو إجراء العد مباشرةً.

بما أن anti-join يعيد صفًا واحدًا لكل صف يتيم، فإن استخدام COUNT(*) عاديًا عليه صحيح هنا؛ إذ يوجد صف واحد بالضبط لكل عميل غير متطابق.

SELECT COUNT(*) AS never_ordered
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

القالب القابل لإعادة الاستخدام

احفظوا هذا الهيكل المؤلف من ثلاثة أسطر؛ فهو يحل عائلة كبيرة من أسئلة المقابلات:

  • FROM keep_table k
  • LEFT JOIN other o ON o.fk = k.id
  • WHERE o.id IS NULL

بدّلوا الجداول والمفاتيح للعثور على المنتجات غير المباعة، والتذاكر غير المسندة، والمستخدمين الذين لم يسجلوا الدخول، وأي شيء يوصف بأنه «X لا يطابقه Y».

تحقق سريع

تحتاجون إلى المنتجات التي لم تظهر مطلقًا في order_items.

مراجعة

يعثر anti-join على الصفوف التي لا تطابقها صفوف أخرى: LEFT JOIN ثم WHERE right_key IS NULL.

  • اختبروا مفتاح JOIN أو المفتاح الأساسي، وليس عمود بيانات يقبل NULL.
  • يجب أن يكون اختبار IS NULL في WHERE، وليس في ON.
  • وهو مكافئ لـ NOT EXISTS؛ ففضّلوه على NOT IN الذي يتعطل عند وجود NULL.
  • اعكسوا ترتيب الجدولين للعثور على الصفوف الفرعية اليتيمة.

قالب واحد وأسئلة كثيرة: «X لا يطابقه Y».

الأسئلة الشائعة

هل درس «العثور على الصفوف دون تطابق (Anti-Join)» مجاني؟

نعم — نص درس «العثور على الصفوف دون تطابق (Anti-Join)» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.

ماذا ستتعلم في «العثور على الصفوف دون تطابق (Anti-Join)»؟

نمط LEFT JOIN / IS NULL للعثور على السجلات孤 والمفقودة تتمرن على SQL Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ SQL Interview Prep؟

لا تُشترط خبرة سابقة. SQL Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «العثور على الصفوف دون تطابق (Anti-Join)»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس SQL Interview Prep هذا؟

نعم. كل درس في SQL Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. LEFT JOIN والحفاظ على الصفوف غير المطابقة
  2. دلالات RIGHT وFULL OUTER JOIN
  3. العثور على الصفوف دون تطابق (Anti-Join)
  4. فخ WHERE في الربط الخارجي
← العودة إلى SQL Interview Prep