إرجاع صفوف Top-N بشكل موثوق
سبب عدم حتمية ORDER BY مع LIMIT دون عامل لكسر التعادل
إرجاع صفوف Top-N بشكل موثوق درس مجاني في SQL Interview Prep على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
الخطأ الخفي في استعلامات Top-N
يبدو الطلب "أعطني أعلى 5 موظفين من حيث الراتب" سهلًا: ORDER BY salary DESC LIMIT 5. لكن المحاورين يضعون فخًا. ماذا لو تعادل ستة أشخاص في الراتب عند الحد الفاصل؟ وماذا لو تعادلت صفوف كثيرة؟
المشكلة الأساسية هي الحتمية: عندما يحتوي مفتاح الفرز على قيم متعادلة، يقطع LIMIT النتائج بصورة اعتباطية، وقد تتغير الصفوف المحددة التي يعيدها بين تشغيل وآخر. يوضح هذا الدرس كيفية جعل استعلامات Top-N موثوقة.
لماذا قد يكون ORDER BY + LIMIT غير حتمي
افترض وجود رواتب تحتل الرتب 4 و5 و6، وجميعها تساوي 50000. يجب أن يعيد ORDER BY salary DESC LIMIT 5 خمسة صفوف بالضبط، لذلك يحتفظ بصفين من الصفوف الثلاثة المتعادلة ويسقط واحدًا، لكن لا توجد قاعدة تحدد أي صفين.
عند تشغيل الاستعلام مرتين، أو بعد أن يغيّر المحسن خطط التنفيذ، قد تحصل على أشخاص مختلفين. وهذا اللاتحديد هو الخطأ الذي يريد المحاورون منك اكتشافه.
SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 5;الإصلاح 1: إضافة مفتاح فاصل فريد
أبسط إصلاح هو جعل ترتيب الفرز محددًا بالكامل بإلحاق عمود فريد، وعادةً ما يكون المفتاح الأساسي. عندئذٍ لا يتساوى أي صفين في المفتاح الكامل، فيصبح القطع حتميًا وقابلًا لإعادة الإنتاج.
لا يغيّر هذا الرواتب التي ستظهر، لكنه يجعل الاختيار بين الصفوف المتعادلة ثابتًا في عمليات التشغيل المختلفة.
SELECT id, name, salary
FROM employees
ORDER BY salary DESC, id ASC
LIMIT 5;الإصلاح 2: تضمين جميع حالات التعادل باستخدام WITH TIES
أحيانًا يكون المتطلب هو "تضمين كل من تعادل مع الحد الفاصل"، وليس إرجاع عدد N من الصفوف بالضبط. توفر SQL القياسية وSQL Server الخيار WITH TIES، الذي يعيد صفوفًا إضافية تطابق قيمة ORDER BY للصف الأخير.
إذا كان الراتب الخامس مشتركًا بين ثلاثة أشخاص، فسيعيد هذا الخيار 7 صفوف. لاحظ أن WITH TIES يتطلب وجود ORDER BY.
SELECT name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST 5 ROWS WITH TIES;وضّح المتطلب أولًا
قبل كتابة الشيفرة، اسأل المحاور: «إذا وُجد تعادل عند الحد الفاصل، فهل تريد بالضبط N صفوف أم جميع الصفوف المتعادلة؟» يوضح هذا السؤال التوضيحي وحده خبرتك المتقدمة.
- بالضبط N صفوف، مع ثبات النتيجة: أضف مفتاحًا فاصلًا فريدًا.
- تضمين جميع حالات التعادل: استخدم
WITH TIESأوRANK. - القيم المميزة: استخدم
DENSE_RANK.
النهج القابل للنقل باستخدام دوال النوافذ
تفتقر محركات كثيرة إلى WITH TIES. ويستخدم النمط القابل للنقل والقوي دالة نافذة للترتيب داخل استعلام فرعي أو CTE، ثم يصفّي النتائج حسب الرتبة. تمنحك ROW_NUMBER بالضبط N صفوف باستخدام مفتاح ترتيب حتمي.
يجب تغليف دالة النافذة، لأنك لا تستطيع الإشارة إليها مباشرةً في WHERE.
SELECT name, salary
FROM (
SELECT name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC, id ASC) AS rn
FROM employees
) ranked
WHERE rn <= 5;استخدام RANK للإبقاء على حالات التعادل
استبدل ROW_NUMBER بـ RANK عندما تريد الإبقاء على جميع الصفوف المتعادلة مع وجود فجوات في الترقيم. فإذا تعادلت ثلاثة صفوف في الرتبة 4، حصلت جميعها على الرتبة 4، وكانت الرتبة التالية هي 7.
تؤدي التصفية باستخدام rank <= 5 إلى إرجاع كل صف يقع ضمن مواضع الرواتب الخمسة الأولى، مع تضمين حالات التعادل.
SELECT name, salary
FROM (
SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) ranked
WHERE rnk <= 5;استخدام DENSE_RANK لأعلى N من القيم المميزة
تعني عبارة "أعلى 3 مستويات رواتب"، وليس أعلى 3 أشخاص، القيم المميزة. تعيّن DENSE_RANK الرتبة نفسها للقيم المتعادلة ولا تتخطى الأرقام، ولذلك يعيد dense_rnk <= 3 كل من يتقاضى واحدًا من أعلى ثلاثة رواتب مميزة.
معرفة دالة الترتيب التي تجيب عن كل صياغة تُعد عامل تمييز كلاسيكيًا.
SELECT name, salary
FROM (
SELECT name, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
FROM employees
) ranked
WHERE drnk <= 3;حالة Top-1 الخاصة
بالنسبة إلى الصف الأعلى، يعمل ORDER BY ... LIMIT 1، لكنه يظل عرضة لحالات التعادل. وإذا أردت كل صف يحتل القيمة العظمى، فقارنها بقيمة max في استعلام فرعي، أو استخدم RANK() = 1.
صيغة الاستعلام الفرعي باستخدام max واضحة وتعمل في أي لهجة.
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);مقارنة الأساليب
ملخص متى تستخدم كل أداة للحصول على Top-N موثوق:
LIMIT+ مفتاح فاصل فريد: بالضبط N صفوف، ثابت، والأبسط.FETCH ... WITH TIES: بالضبط N صفوف بالإضافة إلى حالات التعادل عند الحد الفاصل، وفق SQL القياسية.ROW_NUMBER: بالضبط N صفوف، حتمية، وقابلة للنقل بالكامل.RANK: أعلى N من المواضع مع تضمين جميع حالات التعادل.DENSE_RANK: أعلى N من القيم المميزة.
لمحة عن Top-N لكل مجموعة
يتوسع نهج النوافذ ليشمل حالات كثيرة. أضف PARTITION BY للحصول على أعلى N داخل كل مجموعة، مثل أعلى موظفين اثنين من حيث الدخل في كل قسم. وينطبق مرشح rn <= n نفسه بعد التقسيم.
تُعد مسألة Top-N لكل مجموعة من أكثر مسائل المقابلات الواقعية شيوعًا، وهي مبنية على النمط نفسه الذي تعلمته للتو.
SELECT department, name, salary
FROM (
SELECT department, name, salary,
ROW_NUMBER() OVER (PARTITION BY department
ORDER BY salary DESC, id ASC) AS rn
FROM employees
) ranked
WHERE rn <= 2;اختبار سريع
طابق المتطلب مع الدالة المناسبة.
خلاصة
لإرجاع Top-N بصورة موثوقة:
- يكون
ORDER BY ... LIMITوحده غير حتمي عندما يحتوي مفتاح الفرز على قيم متعادلة. - أضف مفتاحًا فاصلًا فريدًا للحصول على نتائج ثابتة تحتوي على N صفوف بالضبط.
- استخدم
WITH TIESأوRANKللإبقاء على حالات التعادل عند الحد الفاصل. - استخدم
DENSE_RANKللحصول على أعلى N من القيم المميزة. - وضّح دائمًا ما إذا كان المحاور يريد N صفوف بالضبط أم جميع الصفوف المتعادلة.
الأسئلة الشائعة
هل درس «إرجاع صفوف Top-N بشكل موثوق» مجاني؟
نعم — نص درس «إرجاع صفوف Top-N بشكل موثوق» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
ماذا ستتعلم في «إرجاع صفوف Top-N بشكل موثوق»؟
سبب عدم حتمية ORDER BY مع LIMIT دون عامل لكسر التعادل تتمرن على SQL Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ SQL Interview Prep؟
لا تُشترط خبرة سابقة. SQL Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «إرجاع صفوف Top-N بشكل موثوق»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس SQL Interview Prep هذا؟
نعم. كل درس في SQL Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الترتيب حسب عدة أعمدة ووضع NULL
- LIMIT وOFFSET وFETCH FIRST
- إرجاع صفوف Top-N بشكل موثوق
- الترتيب حسب التعبيرات والأسماء المستعارة