0Pricing
SQL Interview Prep · درس

RANK مقابل DENSE_RANK عند التعادل

السؤال الشائع حول الترتيب مع فجوات أو دون فجوات عند تعادل القيم

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

دوال الترتيب الثلاث جنبًا إلى جنب

يوفر SQL ثلاث دوال نافذة للترتيب، وأكثر أسئلة النوافذ شيوعًا هو كيفية اختلافها عند التعادل:

  • ROW_NUMBER — فريدة دائمًا؛ وتحصل الصفوف المتعادلة على أرقام مختلفة عشوائيًا.
  • RANK — تشترك الصفوف المتعادلة في الترتيب، ثم يتخطى الترتيب التالي رقمًا (ويترك فجوة).
  • DENSE_RANK — تشترك الصفوف المتعادلة في الترتيب، ثم لا يتخطى الترتيب التالي أي رقم (ولا توجد فجوة).

إن القدرة على ترديد هذا الفرق فورًا تُعد مؤشرًا موثوقًا في المقابلات.

جدول مثال ملموس

تخيل خمس درجات مرتبة تنازليًا: 100, 90, 90, 80, 70. راقب كيف ترقّمها كل دالة.

  • ROW_NUMBER: 1, 2, 3, 4, 5
  • RANK: 1, 2, 2, 4, 5 (تتخطى 3 بعد التعادل)
  • DENSE_RANK: 1, 2, 2, 3, 4 (من دون تخطٍّ)

احفظ مثال 100/90/90/80/70 — فهو يجيب عن السؤال فورًا.

SELECT
  score,
  ROW_NUMBER()  OVER (ORDER BY score DESC) AS rownum,
  RANK()        OVER (ORDER BY score DESC) AS rnk,
  DENSE_RANK()  OVER (ORDER BY score DESC) AS dense
FROM scores;

كيف يحسب RANK الفجوة

تسند RANK إلى كل صف ترتيبًا يساوي واحدًا زائد عدد الصفوف التي تسبقه دون تعادل في الترتيب. يسبق كل صف من الصفين المتعادلين عند القيمة 90 صف واحد (وهو 100)، لذلك يحصل كلاهما على الترتيب 2. أما القيمة التالية الأقل فتسبقها ثلاثة صفوف، لذا تقفز إلى الترتيب 4.

لهذا تحاكي RANK نظام ترتيب المسابقات: ميداليات فضية متعادلة، ومن دون ميدالية برونزية.

-- scores 100,90,90,80 -> RANK = 1,2,2,4
SELECT score, RANK() OVER (ORDER BY score DESC) AS rnk
FROM scores;

كيف يتجنب DENSE_RANK الفجوة

تسند DENSE_RANK إلى كل صف ترتيبًا يساوي واحدًا زائد عدد القيم المميزة التي تسبق القيمة الحالية. بعد التعادل عند 90، لم تسبق 80 إلا قيمتان مميزتان (100 و90)، لذا تحصل على الترتيب 3 — من دون فجوة.

استخدم DENSE_RANK عندما تهمك مواضع القيم المميزة، مثل «ثاني أعلى راتب» عندما يجب احتساب التعادلات مرة واحدة.

-- scores 100,90,90,80 -> DENSE_RANK = 1,2,2,3
SELECT score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense
FROM scores;

متى تختار كل دالة

دليل سريع لاتخاذ القرار يحب المحاورون سماعه:

  • هل تحتاج إلى صف واحد بالضبط لكل موضع (آخر سجل، أو ترقيم الصفحات)؟ ← ROW_NUMBER.
  • هل تحتاج إلى ترتيب تتشارك فيه القيم المتساوية المرتبة، وتكون الفجوات فيه صحيحة (ترتيب رياضي، أو أفضل 3 نتائج مع تضمين المتعادلين)؟ ← RANK.
  • هل تحتاج إلى القيمة المميزة رقم N (مثل الراتب الأعلى رقم N)؟ ← DENSE_RANK.

يؤثر الاختيار الخاطئ في الصفوف التي يعيدها الاستعلام، لذا اذكر مبرر اختيارك بوضوح.

الترتيب داخل الأقسام

تقبل الدوال الثلاث جميعًا PARTITION BY لترتيب الصفوف بشكل مستقل داخل كل مجموعة. ويُعاد الترتيب في كل قسم بدءًا من المرتبة 1.

في هذا المثال، يرتب كل قسم موظفيه حسب الراتب، مع معالجة حالات التعادل باستخدام DENSE_RANK. يكون صاحب أعلى راتب في كل قسم في المرتبة 1، ويتشارك الموظفون ذوو الرواتب المتساوية المرتبة نفسها.

SELECT
  department,
  name,
  salary,
  DENSE_RANK() OVER (
    PARTITION BY department
    ORDER BY salary DESC
  ) AS salary_rank
FROM employees;

مثال محلول: أفضل 3 نتائج مع تضمين المتعادلين

«أعِد أعلى 3 رواتب لكل قسم، وإذا تعادل عدة أشخاص في المرتبة الثالثة، فضمّنهم جميعًا.» يتطلب ذلك استخدام RANK أو DENSE_RANK، وليس ROW_NUMBER.

يحتفظ استخدام DENSE_RANK <= 3 بأعلى ثلاثة مستويات رواتب مميزة وبكل موظف ينتمي إلى هذه المستويات — وهذا هو المقصود تمامًا بعبارة «مع تضمين المتعادلين».

SELECT department, name, salary, salary_rank
FROM (
  SELECT department, name, salary,
         DENSE_RANK() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS salary_rank
  FROM employees
) t
WHERE salary_rank <= 3;

مثال محلول: ثاني أعلى راتب

إنه أشهر سؤال في مقابلات SQL. تستخدم الإجابة المتينة DENSE_RANK حتى لا تؤدي الرواتب القصوى المكررة إلى حجب القيمة الثانية الفعلية.

إذا كان ثلاثة أشخاص يتقاضون أعلى راتب، فإن DENSE_RANK = 2 يحدد بشكل صحيح الراتب المميز التالي، بينما يعيد ROW_NUMBER = 2 شخصًا آخر من أصحاب أعلى راتب فحسب.

SELECT DISTINCT salary AS second_highest
FROM (
  SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS dr
  FROM employees
) t
WHERE dr = 2;

‏RANK مقابل DENSE_RANK عند البحث عن «المرتبة رقم N»

لماذا نستخدم DENSE_RANK بدلًا من RANK في أسئلة «المرتبة الأعلى رقم N»؟ لأن RANK يترك فجوات. ففي حالة الرواتب 100 و100 و90، تكون قيمة 90 في RANK = 3، لكنها في DENSE_RANK = 2.

إذا كان السؤال يطلب «ثاني أعلى راتب مميز»، فلن تؤدي تصفية RANK = 2 إلى أي نتيجة، بينما تعيد DENSE_RANK = 2 القيمة 90 بشكل صحيح. اربط دائمًا بين عبارة «القيمة المميزة رقم N» وDENSE_RANK.

-- salaries 100,100,90
-- RANK:       1,1,3   -> WHERE rank = 2 returns NOTHING
-- DENSE_RANK: 1,1,2   -> WHERE dense_rank = 2 returns 90

ملاحظات بين اللهجات

الخبر الجيد هو أن ROW_NUMBER وRANK وDENSE_RANK دوال معيارية في SQL، وتعمل بالطريقة نفسها في PostgreSQL وSQL Server وOracle وMySQL 8+ وBigQuery وSnowflake. وقواعد التعامل مع التعادل المذكورة أعلاه عامة في جميعها.

توجد دالة مرتبطة بها، وهي PERCENT_RANK، وتبني على RANK لإعطاء موضع نسبي من 0 إلى 1؛ ومن المفيد ذكرها إذا سأل المحاور عن الترتيب المئيني.

الأخطاء الشائعة

انتبه إلى ما يلي:

  • استخدام ROW_NUMBER للبحث عن «المرتبة الأعلى رقم N»، مما يؤدي إلى فقدان الصفوف المتعادلة.
  • استخدام RANK عندما يكون السؤال متعلقًا بالقيم المميزة، ثم الحصول على نتائج فارغة بسبب الفجوات.
  • نسيان ORDER BY داخل OVER؛ فالترتيب لا معنى له من دونه.
  • تصفية الترتيب مباشرةً في WHERE بدلًا من تصفيته في استعلام خارجي.

تحقق سريع

طبّق قواعد التعامل مع التعادل.

مراجعة: الفجوات مقابل عدم وجود الفجوات

يمكنك الآن اختيار دالة الترتيب المناسبة فورًا:

  • ROW_NUMBER: أرقام فريدة، من دون مراتب مشتركة.
  • RANK: تتشارك القيم المتساوية المرتبة، ثم تظهر فجوة (1،2،2،4).
  • DENSE_RANK: تتشارك القيم المتساوية المرتبة، من دون فجوة (1،2،2،3).
  • «أعلى قيمة مميزة رقم N» ← DENSE_RANK؛ «أفضل N نتائج مع تضمين المتعادلين» ← RANK/DENSE_RANK؛ «صف واحد لكل موضع» ← ROW_NUMBER.

التالي: كيفية تصفية نتيجة نافذة فعلية، إذ لا يمكنك إجراء ذلك في WHERE.

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

هل درس «RANK مقابل DENSE_RANK عند التعادل» مجاني؟

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

ماذا ستتعلم في «RANK مقابل DENSE_RANK عند التعادل»؟

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

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

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

كم من الوقت يستغرق درس «RANK مقابل DENSE_RANK عند التعادل»؟

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

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

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

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

  1. OVER وPARTITION BY وORDER BY
  2. ROW_NUMBER للتسلسل الفريد
  3. RANK مقابل DENSE_RANK عند التعادل
  4. التصفية حسب نتيجة دالة نافذة
← العودة إلى SQL Interview Prep