0Pricing
SQL Interview Prep · درس

الاستعلامات الفرعية العددية في SELECT وWHERE

الاستعلامات الفرعية التي تعيد قيمة واحدة والخطأ عند إرجاعها أكثر من صف

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

ما المقصود بـ Scalar Subquery في المقابلة

الاستعلام الفرعي scalar هو استعلام يعيد صفًا واحدًا وعمودًا واحدًا بالضبط، أي قيمة واحدة. وبما أنه ينتج قيمة واحدة، تتيح لك SQL وضعه تقريبًا في أي موضع يُسمح فيه بوضع قيمة ثابتة: في SELECT وWHERE وHAVING وحتى ORDER BY.

  • يختبر المحاورون مدى معرفتك بقاعدة صف واحد وعمود واحد.
  • الفخ الشائع هو استعلام فرعي يعيد، عن طريق الخطأ، أكثر من صف واحد.

إذا تمكنت من ذكر هذا التعريف بوضوح، فقد اجتزت بالفعل نقطة التحقق الأولى.

استعلام فرعي scalar في قائمة SELECT

يتيح لك وضع استعلام فرعي scalar في قائمة SELECT إرفاق قيمة واحدة محسوبة بكل صف ناتج. نعرض هنا كل موظف بجوار متوسط الراتب على مستوى الشركة.

يُنفذ الاستعلام الفرعي (SELECT AVG(salary) FROM employees) ويختزل الجدول بأكمله إلى رقم واحد، ثم تُكرر تلك القيمة في كل صف.

SELECT
  name,
  salary,
  (SELECT AVG(salary) FROM employees) AS company_avg
FROM employees;

استعلام فرعي scalar في WHERE

يمكن استخدام القيمة الواحدة نفسها لتوجيه عملية التصفية. ومن الأسئلة الشائعة جدًا في المقابلات: اعثر على جميع من يكسبون أكثر من متوسط راتب الشركة.

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

SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

خطأ «أكثر من صف واحد»

هذا هو الخطأ الذي يريد المحاورون منك توقعه. إذا استخدمت استعلامك الفرعي مع = أو > لكنه أعاد عدة صفوف، فسيُصدر المحرك الخطأ التالي:

  • Postgres: more than one row returned by a subquery used as an expression
  • MySQL: Subquery returns more than 1 row

يفشل الاستعلام أدناه لأنه قد يوجد عدة موظفين في القسم 5؛ ولذلك فالاستعلام الفرعي ليس scalar.

SELECT name
FROM employees
WHERE salary = (SELECT salary FROM employees WHERE dept_id = 5);

إجبار الاستعلام الفرعي على أن يكون scalar

هناك طريقتان موثوقتان لضمان الحصول على قيمة واحدة:

  • استخدم دالة تجميعية مثل MAX أو MIN أو AVG؛ فالدوال التجميعية التي لا تستخدم GROUP BY تعيد صفًا واحدًا دائمًا.
  • استخدم LIMIT 1 (في Postgres/MySQL) أو FETCH FIRST 1 ROW ONLY بعد ORDER BY.

يطلب الإصدار المصحح أدناه أعلى راتب واحد في القسم 5.

SELECT name
FROM employees
WHERE salary = (
  SELECT MAX(salary) FROM employees WHERE dept_id = 5
);

تعيد الاستعلامات الفرعية scalar قيمة NULL عند عدم وجود صفوف

إليك نقطة دقيقة في المقابلات: إذا طابق الاستعلام الفرعي scalar صفرًا من الصفوف، فلا يُصدر خطأ، بل يعيد NULL. ثم تنتقل قيمة NULL هذه إلى نتيجة المقارنة.

وبما أن salary > NULL تُقيّم إلى UNKNOWN (وليس true)، فإن الاستعلام الخارجي لا يعيد أي صفوف. يتوقع المرشحون غالبًا حدوث خطأ هنا؛ لكن الإجابة الصحيحة هي نتيجة فارغة بصمت.

SELECT name, salary
FROM employees
WHERE salary > (
  SELECT AVG(salary) FROM employees WHERE dept_id = 9999
);

مثال تطبيقي: أصحاب الرواتب الأعلى من المتوسط مع بيان الفارق

لنجمع بين موضعي الاستخدام. سنعرض كل موظف راتبه أعلى من المتوسط، ومقدار تجاوزه للمتوسط. يظهر الاستعلام الفرعي scalar نفسه في SELECT وWHERE.

قد يسأل المحاور عما إذا كان الاستعلام الفرعي يُنفذ مرتين. منطقيًا يظهر مرتين، لكن يمكن لمحسّن جيد أن يقيّم الاستعلام الفرعي غير المرتبط مرة واحدة ويعيد استخدام نتيجته.

SELECT
  name,
  salary,
  salary - (SELECT AVG(salary) FROM employees) AS above_avg
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
ORDER BY above_avg DESC;

استعلام فرعي scalar في ORDER BY

بما أن الاستعلام الفرعي scalar ليس سوى قيمة، فمن القانوني استخدامه أيضًا في ORDER BY. ونادرًا ما يكون هذا الأسلوب هو الأنظف، لكن المحاورين يحبون التأكد من معرفتك بأنه مسموح.

نرتب هنا الأقسام حسب قيمة مستخرجة من جدول آخر، وهي عدد الموظفين في كل قسم، من دون استخدام عملية ربط.

SELECT d.dept_name
FROM departments d
ORDER BY (
  SELECT COUNT(*) FROM employees e WHERE e.dept_id = d.id
) DESC;

التمييز بين Scalar وCorrelated

يشير مثال ORDER BY أعلاه، من دون إظهار ذلك مباشرة، إلى d.id من الاستعلام الخارجي؛ وهذا يجعله استعلامًا فرعيًا scalar مرتبطًا، يُنفذ مرة لكل صف خارجي.

يحب المحاورون هذا التمييز:

  • الاستعلام الفرعي scalar غير المرتبط: مستقل بذاته ويُنفذ مرة واحدة.
  • الاستعلام الفرعي scalar المرتبط: يشير إلى الصف الخارجي ويُنفذ مرة لكل صف.

كلاهما يظل scalar (أي يعيد قيمة واحدة)، لكن الأداء يختلف اختلافًا كبيرًا.

متى لا تستخدم استعلامًا فرعيًا scalar

يُعد الاستعلام الفرعي scalar المرتبط في قائمة SELECT مريحًا، لكنه قد يكون بطيئًا في الجداول الكبيرة، لأنه يُنفذ لكل صف. ويتوقع المحاورون منك معرفة البدائل:

  • استخدام LEFT JOIN مع جدول مشتق مُجمّع مسبقًا.
  • استخدام دالة نافذة مثل AVG(salary) OVER ().

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

SELECT
  name,
  salary,
  AVG(salary) OVER () AS company_avg
FROM employees;

خلاصة تصلح للمقابلة

إذا طُلب منك تعريف الاستعلام الفرعي scalar، فقل: «الاستعلام الفرعي scalar يعيد صفًا واحدًا وعمودًا واحدًا، ولذلك يتصرف كقيمة واحدة ويمكن استخدامه في أي موضع يُسمح فيه باستخدام قيمة ثابتة. وإذا أعاد أكثر من صف واحد، يُصدر المحرك خطأ؛ وإذا لم يُعد أي صفوف، فإنه ينتج NULL.»

تغطي هذه الجملة الواحدة التعريف وحالة الخطأ وحالة NULL الخاصة، وهي الأمور الثلاثة التي يبحث عنها كل محاور.

تحقق سريع

اختبر فهمك لسلوك الاستعلام الفرعي scalar.

مراجعة

أصبحت الآن متمكنًا من الاستعلامات الفرعية scalar:

  • التعريف: صف واحد وعمود واحد، ويمكن استخدامها مثل القيمة الثابتة في SELECT وWHERE وHAVING وORDER BY.
  • تؤدي الصفوف المتعددة مع =/> إلى حدوث خطأ؛ ويمكن ضمان إنتاج قيمة واحدة باستخدام دالة تجميعية أو LIMIT 1.
  • تنتج الصفوف الصفرية قيمة NULL، مما يؤدي بصمت إلى استبعاد الصفوف من عملية التصفية.
  • تُنفذ الاستعلامات الفرعية scalar المرتبطة مرة لكل صف؛ لذا يُفضل استخدام عمليات الربط أو دوال النافذة عندما يكون الأداء مهمًا.

التالي: الاستعلامات الفرعية في جملة FROM، حيث تكون النتيجة جدولًا افتراضيًا كاملًا.

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

هل درس «الاستعلامات الفرعية العددية في SELECT وWHERE» مجاني؟

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

ماذا ستتعلم في «الاستعلامات الفرعية العددية في SELECT وWHERE»؟

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

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

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

كم من الوقت يستغرق درس «الاستعلامات الفرعية العددية في SELECT وWHERE»؟

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

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

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

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

  1. الاستعلامات الفرعية العددية في SELECT وWHERE
  2. الاستعلامات الفرعية في عبارة FROM (الجداول المشتقة)
  3. الاستعلامات الفرعية باستخدام IN وANY وALL
  4. أداء EXISTS مقابل IN
← العودة إلى SQL Interview Prep