0Pricing
Coding Interview Prep · درس

إرجاع NULL عند عدم وجود قيمة رقم N

الحالة الطرفية المحببة لمسؤولي المقابلات: معالجة قلة الصفوف بسلاسة

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

الحالة الحدية التي يحبها المحاورون

بعد أن تنجح في كتابة استعلام القيمة ذات الترتيب N من الأعلى، يضيف المحاور: «ماذا لو كان الجدول يحتوي على رواتب مميزة أقل من N؟ أريد قيمة NULL واحدة، لا نتيجة فارغة».

هذا هو السؤال الذي يميّز بين المرشحين الذين حفظوا استعلامًا والذين يفهمون سلوك مجموعة النتائج. تعيد حلول كثيرة صفر صفوف بصمت بدلًا من صف واحد يحتوي على NULL.

يدور هذا الدرس بالكامل حول فرض إخراج صف واحد بالضبط، تكون قيمته NULL عندما لا توجد قيمة ذات الترتيب N.

لماذا لا يعيد DENSE_RANK وحده أي صفوف

تذكّر الاستعلام القياسي للقيمة ذات الترتيب N من الأعلى. إذا لم توجد سوى رواتب مميزة اثنتين وطلبت القيمة الثالثة، فلن يطابق WHERE rnk = 3 أي شيء، ولذلك يعيد الاستعلام مجموعة فارغة: صفر صفوف.

المجموعة الفارغة ليست كصف يحتوي على NULL. إذا نصت المواصفات على «إعادة NULL»، فستفشل النتيجة الفارغة في الاختبار، رغم أن المنطق الأساسي صحيح.

SELECT salary
FROM (
  SELECT salary,
         DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
  FROM employee
) t
WHERE rnk = 3;  -- returns NO rows if fewer than 3 distinct salaries

الحل الأول: تغليف الاستعلام داخل SELECT خارجي

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

هذه هي الإجابة القياسية للنسخة الشبيهة بمسائل LeetCode التي تطلب «إعادة NULL»، وهي تعمل في جميع لهجات SQL.

SELECT (
  SELECT DISTINCT salary
  FROM employee
  ORDER BY salary DESC
  LIMIT 1 OFFSET 2   -- N = 3
) AS third_highest;

لماذا تنجح حيلة الاستعلام الفرعي scalar

تتحد قاعدتان لتحقيق السلوك المطلوب:

  • يجب أن يعيد الاستعلام الفرعي scalar قيمة واحدة على الأكثر. وإذا لم يُرجع أي صفوف، فإن SQL تستبدل النتيجة بـ NULL.
  • إن SELECT الخارجي من دون FROM (أو باستخدام مصدر يعيد صفًا واحدًا) يعيد صفًا واحدًا بالضبط دائمًا.

لذلك، عندما يجد الاستعلام الداخلي القيمة ذات الترتيب N تحصل عليها، وعندما لا يجد شيئًا تحصل على صف واحد يحتوي على NULL. وهذا يطابق تمامًا السلوك الذي حدده المحاور.

الحل الأول باستخدام نسخة DENSE_RANK

يعمل الغلاف نفسه مع حل الدوال النافذة. ضع الاستعلام المرتّب داخل الاستعلام الفرعي scalar؛ فإذا لم يوجد صف يحمل الترتيب N، يعيد الاستعلام الفرعي NULL، بينما يظل SELECT الخارجي يعيد صفًا واحدًا.

SELECT (
  SELECT salary
  FROM (
    SELECT salary,
           DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
    FROM employee
  ) t
  WHERE rnk = 3
) AS third_highest;

الحل الثاني: يعيد MAX القيمة NULL تلقائيًا

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

لكن توسيع التعشيق الصرف لـ MAX إلى قيمة N عشوائية يصبح معقدًا، لذلك يُفضَّل استخدام هذا الحل تحديدًا لحالة ثاني أعلى قيمة.

SELECT MAX(salary) AS second_highest
FROM employee
WHERE salary < (SELECT MAX(salary) FROM employee);

الحل الثالث: استخدام COALESCE مع قيمة احتياطية

إذا كانت بيئتك تضمن وجود صف واحد، لكن القيمة قد تكون مفقودة لسبب آخر، فيمكنك تغليف النتيجة بـ COALESCE لتوفير قيمة افتراضية صريحة.

ملاحظة: لا تفيد COALESCE إلا بعد وجود صف. فهي لا تحوّل مجموعة نتائج فارغة إلى صف. لذلك ادمجها مع غلاف الاستعلام الفرعي scalar (الذي يضمن وجود صف)، ثم استخدم COALESCE للقيمة إذا كنت تريد قيمة غير NULL، مثل 0.

SELECT COALESCE((
  SELECT DISTINCT salary
  FROM employee
  ORDER BY salary DESC
  LIMIT 1 OFFSET 2
), 0) AS third_highest_or_zero;

ما الذي لا يصلح المشكلة

احذر من الحلول التي تبدو صحيحة لكنها تفشل:

  • إضافة COALESCE مباشرةً حول استعلام يعيد صفر صفوف لا تفعل شيئًا؛ فلا يوجد صف تعمل عليه COALESCE.
  • لدى IFNULL وISNULL القيد نفسه الموجود لدى COALESCE.
  • إضافة LIMIT 1 لا تنشئ صفًا عندما لا يطابق أي صف الشرط.

يجب حل مشكلة عدد الصفوف باستخدام غلاف الاستعلام الفرعي scalar أو دالة تجميع، وليس باستخدام دوال استبدال NULL وحدها.

مثال تطبيقي: طلب القيمة الثالثة من قيمتين

الرواتب: 500، و500، و300. لا توجد سوى قيمتي راتب مميزتين، هما 500 و300، ولذلك لا توجد قيمة ثالثة من الأعلى.

  • استخدام DENSE_RANK مباشرةً مع WHERE rnk = 3: يعيد صفر صفوف. ويفشل في تلبية المواصفات.
  • غلاف الاستعلام الفرعي scalar: لا يجد الاستعلام الداخلي شيئًا، لذلك يعيد SELECT الخارجي صفًا واحدًا: NULL. وينجح في تلبية المواصفات.
  • COALESCE(..., 0): يعيد صفًا واحدًا يحتوي على 0، إذا كانت القيمة الافتراضية الرقمية مطلوبة.

شرح الحل أثناء المقابلة

احصل على نقاط إضافية من خلال شرح تفكيرك:

  • «يعيد الاستعلام الساذج مجموعة فارغة، وليس NULL، لذلك سأغلفه في استعلام فرعي scalar لضمان وجود صف واحد».
  • «يُقيَّم الاستعلام الفرعي scalar الذي لا يطابق أي صفوف على أنه NULL، وهذا يطابق المواصفات تمامًا».
  • «إذا كنتم تفضلون قيمة افتراضية مثل 0 بدلًا من NULL، فسأضيف COALESCE حول الاستعلام الفرعي».

إظهار فهمك للفرق بين دلالات عدد الصفوف ودلالات القيمة هو جوهر هذا السؤال.

جمع جميع الأجزاء

حل متين وقابل للمعلمات لإيجاد القيمة ذات الترتيب N من الأعلى أو NULL: رتّب الرواتب المميزة، ثم صفِّها حسب الترتيب N داخل استعلام فرعي scalar، ودَع SELECT الخارجي يضمن وجود صف واحد.

يتعامل هذا الاستعلام مع التكرارات (باستخدام DENSE_RANK)، ويتعمم على أي قيمة N، ويعيد NULL بسلاسة عندما تتجاوز N عدد الرواتب المميزة.

SELECT (
  SELECT salary
  FROM (
    SELECT salary,
           DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
    FROM employee
  ) t
  WHERE rnk = :n
  LIMIT 1
) AS nth_highest;

تحقق سريع

فكّر في الفرق بين عدد الصفوف وقيم NULL.

خلاصة

عندما تتجاوز N عدد الرواتب المميزة المتاحة، يعيد استعلام الترتيب العادي مجموعة فارغة، وليس NULL.

  • غلّف استعلام القيمة ذات الترتيب N من الأعلى في استعلام فرعي scalar داخل SELECT خارجي، حتى ينتج صفًا واحدًا دائمًا، ويعيد NULL عندما لا تطابق أي قيمة الشرط.
  • يعيد نمط MAX المتداخل القيمة NULL تلقائيًا في حالة ثاني أعلى قيمة.
  • لا تستبدل COALESCE القيمة إلا بعد وجود صف؛ فهي لا تحوّل صفر صفوف إلى صف واحد.

ميّز دائمًا بين عدد الصفوف والقيمة عندما يطلب المحاور التعامل بسلاسة مع NULL.

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

هل درس «إرجاع NULL عند عدم وجود قيمة رقم N» مجاني؟

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

ماذا ستتعلم في «إرجاع NULL عند عدم وجود قيمة رقم N»؟

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

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

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

كم من الوقت يستغرق درس «إرجاع NULL عند عدم وجود قيمة رقم N»؟

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

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

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

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

  1. ثاني أعلى راتب بخمس طرق
  2. القيمة الأعلى رقم N باستخدام DENSE_RANK
  3. أعلى دخل في كل قسم
  4. إرجاع NULL عند عدم وجود قيمة رقم N
← العودة إلى Coding Interview Prep