0Pricing
SQL Interview Prep · درس

ROW_NUMBER للتسلسل الفريد

تعيين رقم صف حتمي داخل كل قسم

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

ما الذي يضمنه ROW_NUMBER

تسند ROW_NUMBER() عددًا صحيحًا فريدًا ومتتاليًا بلا فجوات لكل صف ضمن قسمه، بدءًا من 1، وفقًا لـ ORDER BY الخاص بالنافذة. لا يشترك صفان في الرقم نفسه مطلقًا، حتى عندما تكون قيم الترتيب متطابقة.

هذا التفرد تحديدًا هو سبب لجوء المحاورين إليها لحل مسائل «اختيار صف واحد لكل مجموعة» وإزالة التكرار. أما دوال الترتيب الأخرى (RANK وDENSE_RANK) فلا تضمن التفرد عند التعادل.

استعلام ROW_NUMBER بالحد الأدنى

تُرقّم أبسط صيغة مجموعة النتائج بأكملها وفق ترتيب تختاره. تحتاج ROW_NUMBER دائمًا إلى ORDER BY داخل OVER — فمن دونه سيكون الترقيم عشوائيًا، كما أن معظم المحركات ترفضه أو تحذّر منه.

في هذه الحالة، سيكون الموظف الأحدث تعيينًا هو الصف 1 عند الترتيب حسب تاريخ التعيين تنازليًا.

SELECT
  name,
  hire_date,
  ROW_NUMBER() OVER (ORDER BY hire_date DESC) AS rn
FROM employees;

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

أضف PARTITION BY لترقيم الصفوف بشكل مستقل داخل كل مجموعة. يُعاد العداد إلى 1 عند كل قيمة تقسيم جديدة.

في المثال، يحصل كل قسم على تسلسل خاص به من 1 و2 و3، مرتبًا حسب الراتب. ويكون صاحب أعلى راتب في كل قسم هو الرقم 1 — وهي نقطة الانطلاق لنمط أعلى N لكل مجموعة.

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

ROW_NUMBER والتعادلات: لا توجد تعادلات

نقطة مهمة في المقابلات: عندما تتساوى قيم الترتيب في صفين، تمنحهما ROW_NUMBER رقمين مختلفين رغم ذلك. ويكون تحديد أيهما يحصل على الرقم الأصغر غير حتمي ما لم تضف عمودًا لكسر التعادل.

  • كانت RANK ستمنح الصفوف المتعادلة الترتيب نفسه.
  • تختار ROW_NUMBER ترتيبًا عشوائيًا بين الصفوف المتعادلة.

لجعل النتائج قابلة لإعادة الإنتاج، أضف دائمًا عمودًا فريدًا لكسر التعادل إلى ORDER BY.

SELECT
  name,
  salary,
  ROW_NUMBER() OVER (
    ORDER BY salary DESC, employee_id  -- employee_id breaks ties deterministically
  ) AS rn
FROM employees;

قاعدة كسر التعادل الحتمي

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

قاعدة عامة: أضف مفتاحًا أساسيًا أو عمودًا فريدًا آخر باعتباره مفتاح الفرز النهائي كلما وجب أن تكون النتيجة مستقرة.

-- Unstable: many rows can share the same created_at
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC)

-- Stable: id guarantees a single deterministic winner
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC, id DESC)

مثال محلول: أحدث طلب لكل عميل

سؤال أساسي: «أعد أحدث طلب لكل عميل». رقّم الطلبات لكل عميل حسب التاريخ تنازليًا، ثم احتفظ بالصفوف التي تحقق rn = 1 في استعلام خارجي.

بما أن ROW_NUMBER يضمن وجود صف واحد بالضبط يحمل الرقم 1 في كل قسم، فستحصل على صف واحد بالضبط لكل عميل — من دون تكرارات حتى إذا اشترك طلبان في الطابع الزمني نفسه (إذ يحسم كسر التعادل الأمر).

SELECT customer_id, order_id, order_date, amount
FROM (
  SELECT
    customer_id, order_id, order_date, amount,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY order_date DESC, order_id DESC
    ) AS rn
  FROM orders
) t
WHERE rn = 1;

مثال محلول: إزالة تكرار الصفوف

تُعد ROW_NUMBER الأداة الأوضح لإزالة التكرار. قسّم حسب الأعمدة التي تحدد التكرار، ورتّب وفق قاعدة تفضيل، ثم احتفظ بالصفوف التي تحقق rn = 1.

في هذه الحالة، نعدّ الصفوف التي لها البريد الإلكتروني نفسه مكررة، ونحتفظ بالصف الذي أُنشئ أولًا. وكل ما يحقق rn > 1 هو تكرار يمكن حذفه أو تجاهله.

SELECT id, email, created_at
FROM (
  SELECT
    id, email, created_at,
    ROW_NUMBER() OVER (
      PARTITION BY email
      ORDER BY created_at ASC, id ASC
    ) AS rn
  FROM users
) t
WHERE rn = 1;

ROW_NUMBER لترقيم الصفحات

قبل أن يصبح OFFSET/FETCH متاحًا على نطاق واسع، كانت ROW_NUMBER أساس ترقيم الصفحات، ولا تزال كذلك في SQL Server والعديد من مهام ETL. رقّم الصفوف بترتيب مستقر، ثم صفِّ نطاقًا مرقمًا في استعلام خارجي.

تنبيه في المقابلات: لا يكون ترقيم الصفحات صحيحًا إلا إذا كان الترتيب حتميًا؛ وإلا فقد يظهر الصف نفسه في صفحتين أو يُتخطى بالكامل.

SELECT *
FROM (
  SELECT *, ROW_NUMBER() OVER (ORDER BY created_at, id) AS rn
  FROM articles
) t
WHERE rn BETWEEN 21 AND 40;  -- page 2, 20 per page

تعيين تسلسل لإعادة ترتيب البيانات

أحيانًا تحتاج فقط إلى فهرس متسلسل، مثل إعادة ترقيم الصفوف بعد فرزها، أو إنشاء تسمية من 1 إلى N، أو إقران الصفوف بسلسلة مولدة. ينتج استخدام ROW_NUMBER حسب الترتيب المطلوب تسلسلًا متتابعًا بلا فجوات.

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

SELECT
  ROW_NUMBER() OVER (ORDER BY score DESC, player_id) AS leaderboard_position,
  player_id,
  score
FROM scores;

ROW_NUMBER مقابل COUNT للصف رقم N

عندما يُطلب منك «ثالث أحدث طلب» أو «الصف الثاني»، استخدم ROW_NUMBER وصفِّ حسب القيمة المحددة في استعلام خارجي. وبما أن الترقيم فريد، فإن rn = 3 يعيد صفًا واحدًا بالضبط.

قارن ذلك بـ RANK: إذا كنت تريد القيمة المميزة الثانية (مثل ثاني أعلى راتب مع احتساب التعادلات)، فإن ROW_NUMBER ليست الأداة المناسبة — بل تحتاج إلى DENSE_RANK، الذي سيأتي شرحه في الدرس التالي.

SELECT order_id, order_date
FROM (
  SELECT order_id, order_date,
         ROW_NUMBER() OVER (ORDER BY order_date DESC, order_id DESC) AS rn
  FROM orders
) t
WHERE rn = 3;  -- exactly the 3rd most recent order

مراجعة الأخطاء الشائعة

احرص على تذكر النقاط التالية تحت ضغط المقابلة:

  • تكون ROW_NUMBER فريدة دائمًا ومتتالية بلا فجوات داخل القسم.
  • تحتاج إلى ORDER BY في OVER؛ ومن دون كاسر تعادل فريد، تصبح النتائج غير حتمية عند التعادل.
  • لا يمكن تصفيتها في WHERE — بل يجب وضعها داخل استعلام فرعي أو CTE.
  • استخدمها للحصول على صف واحد لكل مجموعة، وإزالة التكرار، وترقيم الصفحات؛ واستخدم DENSE_RANK عندما يجب أن تشترك الصفوف المتعادلة في الرقم نفسه.

تحقق سريع

كيف يتعامل ROW_NUMBER مع الصفوف المتعادلة في قيمة ORDER BY؟

مراجعة: الترقيم الحتمي

ROW_NUMBER هي أداتك للترقيم الفريد والمتتالي بلا فجوات داخل الأقسام. لقد تعلمت كيفية:

  • ترقيم مجموعات كاملة ومجموعات داخل كل قسم.
  • إضافة كاسر تعادل فريد للحصول على نتائج حتمية وقابلة لإعادة الإنتاج.
  • حل مسائل أحدث صف لكل مفتاح، وإزالة التكرار، وترقيم الصفحات، والصف رقم N، وذلك بتصفية rn في استعلام خارجي.

بعد ذلك، سترى كيف تمنح RANK وDENSE_RANK الصفوف المتعادلة الرقم نفسه عمدًا — وكيف يختلف سلوكهما تجاه الفجوات.

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

هل درس «ROW_NUMBER للتسلسل الفريد» مجاني؟

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

ماذا ستتعلم في «ROW_NUMBER للتسلسل الفريد»؟

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

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

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

كم من الوقت يستغرق درس «ROW_NUMBER للتسلسل الفريد»؟

معظم دروس 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