0Pricing
SQL Interview Prep · درس

تشريح استعلام فرعي مترابط

كيفية إشارة الاستعلام الداخلي إلى الصف الخارجي ونموذج التنفيذ لكل صف

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

ما الذي يجعل الاستعلام الفرعي مرتبطًا

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

  • غير المرتبط: يُقيَّم مرة واحدة، ثم يُعاد استخدام النتيجة لكل صف خارجي.
  • المرتبط: يُعاد تقييمه مرة لكل صف خارجي لأنه يعتمد على ذلك الصف.

العلامة الدالة هي ظهور عمود من الجدول الخارجي داخل الاستعلام الداخلي. لاحظوا ذلك، وستتمكنون من تسمية النمط فورًا.

نموذج التنفيذ لكل صف

تصوّر أن المحرّك يمرّ على الصفوف الخارجية واحدًا تلو الآخر. لكل صف خارجي، يُدخل المحرّك قيم ذلك الصف في الاستعلام الداخلي، وينفّذه، ثم يستخدم النتيجة لاتخاذ قرار أو إجراء عملية حسابية.

هذا هو النموذج الذهني الذي يريد منك القائمون على المقابلة شرحه لفظيًا: "يُنفَّذ الاستعلام الداخلي مرة واحدة لكل صف خارجي."

وتشير هذه الصياغة أيضًا إلى سؤال المتابعة التقليدي: قد تكون الاستعلامات الفرعية المترابطة بطيئة لأن الاستعلام الداخلي قد يُنفَّذ آلاف المرات. سنعالج ذلك في الدرس 4.

اكتشاف المرجع الخارجي

هنا يقود جدول employees والاسم المستعار الخارجي للموظف ذي الراتب e1 استعلامًا داخليًا يقرأ e1.dept_id. هذا المرجع إلى الصف الخارجي هو ما يحقق الترابط.

إذا أزلت بادئة الاسم المستعار، فلن يعود الاستعلام الداخلي قابلًا للترجمة بمفرده. وهذا الاعتماد هو تحديدًا ما يجعله استعلامًا مترابطًا.

SELECT e1.name, e1.salary
FROM employees e1
WHERE e1.salary > (
    SELECT AVG(e2.salary)
    FROM employees e2
    WHERE e2.dept_id = e1.dept_id
);

قراءة ذلك الاستعلام بصوت عالٍ

حوّل الاستعلام السابق إلى لغة إنجليزية بسيطة بالطريقة التي ستستخدمها في مقابلة:

"لكل موظف e1، اعثر على متوسط راتب قسمه، واحتفظ بالموظف فقط إذا كان راتبه أكبر من متوسط راتب ذلك القسم."

يربط شرط WHERE e2.dept_id = e1.dept_id في الاستعلام الداخلي المتوسط بقسم هذا الموظف تحديدًا. ومن دون هذا السطر، ستقارن الجميع بمتوسط رواتب الشركة بأكملها.

الأسماء المستعارة إلزامية

عندما يلمس الاستعلامان الداخلي والخارجي الجدول نفسه، يجب استخدام اسم مستعار لكل منهما حتى يعرف المحرّك الصف الذي ينتمي إليه العمود.

  • e1 = الصف الخارجي الذي يجري اختباره.
  • e2 = الفحص الداخلي للجدول.

إذا حذفت الأسماء المستعارة، يصبح dept_id غامضًا؛ وعندها قد يربطه كثير من المحرّكات بالجدول الداخلي بصمت، مما يؤدي إلى كسر الترابط. وغالبًا ما يضع القائمون على المقابلات هذا الخطأ تحديدًا.

الاستعلام الفرعي المترابط في SELECT

لا تقتصر الاستعلامات الفرعية المترابطة على WHERE. فعند وضعها في قائمة SELECT، تنتج عمودًا محسوبًا يُقيَّم أيضًا لكل صف خارجي.

في المثال أدناه، يوضّح كل طلب عدد الطلبات الأخرى التي أجراها العميل نفسه. ويحدث الترابط الداخلي من خلال o.customer_id.

SELECT o.order_id,
       o.customer_id,
       (SELECT COUNT(*)
        FROM orders o2
        WHERE o2.customer_id = o.customer_id) AS customer_order_count
FROM orders o;

Scalar يعني قيمة واحدة بالضبط

يجب أن يعيد الاستعلام الفرعي المترابط المستخدم في SELECT أو المقارن بـ = أو > أو < قيمة scalar واحدة لكل صف خارجي.

إذا أعاد أكثر من صف، فستصدر قاعدة البيانات خطأ مثل "يعيد الاستعلام الفرعي أكثر من صف واحد."

تضمن الدوال التجميعية مثل COUNT أو MAX أو AVG قيمة واحدة، ولذلك يشيع استخدامها داخل الاستعلامات الفرعية المترابطة scalar. إن معرفة هذه القاعدة تمنع مفاجأة شائعة أثناء التشغيل.

عندما يعيد الاستعلام الفرعي NULL

قد لا يجد الاستعلام الفرعي المترابط scalar أي صفوف داخلية مطابقة. عندها تعيد الدالة التجميعية NULL، أو تعيد 0 في حالة COUNT.

تنتقل قيمة NULL هذه إلى التعبير الخارجي. وتنتج المقارنات مع NULL القيمة UNKNOWN، لذلك قد يُستبعد الصف الخارجي بصمت.

إذا احتجت إلى قيمة بديلة، فأحط الاستعلام الفرعي بالدالة COALESCE. يحب القائمون على المقابلات السؤال عما يحدث عند عدم تطابق أي صف داخلي، ويتوقعون منك ذكر سلوك NULL.

SELECT c.customer_id,
       COALESCE((SELECT MAX(o.amount)
                 FROM orders o
                 WHERE o.customer_id = c.customer_id), 0) AS biggest_order
FROM customers c;

مثال تطبيقي: تاريخ أحدث طلب

مهمة شائعة: عرض كل عميل مع تاريخ أحدث طلب له. ويمكن تنفيذ ذلك مباشرةً باستخدام استعلام فرعي مترابط في SELECT.

لكل صف عميل، يعثر الاستعلام الداخلي على أكبر تاريخ طلب لذلك العميل تحديدًا من خلال o.customer_id = c.customer_id.

SELECT c.customer_id,
       c.name,
       (SELECT MAX(o.order_date)
        FROM orders o
        WHERE o.customer_id = c.customer_id) AS last_order_date
FROM customers c;

لماذا قد يكون بطيئًا

بما أن الاستعلام الداخلي يُنفَّذ مرة لكل صف خارجي، فقد يؤدي الاستعلام الفرعي المترابط على جدول خارجي كبير إلى ملايين عمليات التنفيذ الداخلية.

  • يسمح الفهرس الموجود على العمود المترابط، وهو هنا orders.customer_id، بإتمام كل عملية داخلية بسرعة.
  • من دون فهرس، قد تفحص كل عملية الجدول بأكمله، مما يؤدي تقريبًا إلى حجم عمل مقداره O(n*m).

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

مقارنة مباشرة بين المترابط وغير المترابط

الفرق بينهما سطر واحد. تقارن النسخة غير المترابطة الجميع بمتوسط الشركة؛ أما النسخة المترابطة فتقارن كل شخص بقسمه هو.

اقرأ النسختين ولاحظ كيف يغيّر السطر الوحيد WHERE e2.dept_id = e1.dept_id المعنى بأكمله.

-- Uncorrelated: one global average, computed once
SELECT name FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

-- Correlated: per-department average, recomputed per row
SELECT e1.name FROM employees e1
WHERE e1.salary > (
    SELECT AVG(e2.salary) FROM employees e2
    WHERE e2.dept_id = e1.dept_id
);

تحقق سريع

اختبر مدى استيعابك لما يعرّف الاستعلام الفرعي المترابط.

مراجعة: بنية الاستعلام الفرعي المترابط

أهم النقاط:

  • يشير الاستعلام الفرعي المترابط إلى الصف الخارجي ويُنفَّذ مرة واحدة لكل صف خارجي.
  • استخدم اسمًا مستعارًا لكل جدول عندما يكونان الجدول نفسه، للحفاظ على وضوح الترابط.
  • يجب أن يعيد الاستخدام scalar قيمة واحدة بالضبط؛ أما عدم وجود مطابقات فينتج NULL، لذا استخدم COALESCE للحماية.
  • يمكن أن يوجد في SELECT أو WHERE، ويعتمد أداؤه بدرجة كبيرة على فهرسة العمود المترابط.

اذكر في المقابلة عبارة "يُنفَّذ مرة واحدة لكل صف خارجي"، وستكون قد أتقنت المفهوم الأساسي.

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

هل درس «تشريح استعلام فرعي مترابط» مجاني؟

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

ماذا ستتعلم في «تشريح استعلام فرعي مترابط»؟

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

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

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

كم من الوقت يستغرق درس «تشريح استعلام فرعي مترابط»؟

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

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

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

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

  1. تشريح استعلام فرعي مترابط
  2. تجميعات كل مجموعة دون GROUP BY
  3. EXISTS وNOT EXISTS المترابطان
  4. إعادة كتابة الاستعلامات الفرعية المترابطة كعمليات ربط
← العودة إلى SQL Interview Prep