0Pricing
Coding Interview Prep · درس

إزالة تكرار الصفوف بأمان

إزالة الصفوف المتطابقة والمتشابهة مع الاحتفاظ بسجل أساسي واحد

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

مشكلة إزالة التكرارات

«يحتوي هذا الجدول على صفوف مكررة. أزلها، مع الاحتفاظ بنسخة واحدة من كل صف.» تتضمن جميع مقابلات هندسة البيانات تقريبًا سؤالًا من هذا النوع. ويتمثل التحدي في تنفيذ ذلك بأمان: الاحتفاظ بصف أساسي واحد بالضبط، وعدم حذف سجلات مختلفة بالخطأ لمجرد أنها تبدو متشابهة.

سنتناول اكتشاف التكرارات، واختيار النسخة التي يجب الاحتفاظ بها، وإزالة التكرارات في عبارة SELECT، وحذف التكرارات فعليًا من جدول.

حدّد التكرار أولًا

أول سؤال ينبغي طرحه على المُحاوِر هو: «ما الذي يجعل صفَّين مكررين؟» وتشمل الخيارات ما يلي:

  • التكرارات المطابقة تمامًا: جميع الأعمدة متطابقة.
  • التكرارات بحسب المفتاح: لهما مفتاح العمل نفسه، مثل email نفسه، لكن قد تختلف الأعمدة الأخرى.

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

اكتشاف التكرارات

للعثور على المفاتيح المكررة، جمّع البيانات بحسب الأعمدة التي تحدد التكرار، واحتفظ بالمجموعات التي يزيد عددها على واحد. يوضح لك ذلك المفاتيح المتأثرة وعدد النسخ الموجودة قبل تغيير أي شيء.

يُعد تشغيل استعلام اكتشاف أولًا ممارسة جيدة يجدر بك ذكرها: إذ تتحقق من حجم المشكلة قبل الحذف.

SELECT email, COUNT(*) AS copies
FROM users
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY copies DESC;

التكرارات المطابقة تمامًا: DISTINCT

إذا كانت التكرارات متطابقة فعلًا في جميع الأعمدة، فإن إنشاء عرض مُزال التكرارات للقراءة فقط يكون بسيطًا بقدر استخدام SELECT DISTINCT *. كما تزيل UNION، من دون ALL، الصفوف المكررة.

لكن DISTINCT يفيد فقط عندما تريد إزالة التكرارات من الصف بأكمله ولا تحتاج إلى اختيار أي نسخة ستحتفظ بها. أما في حالة التكرارات المعتمدة على المفتاح، حيث تختلف الأعمدة، فتحتاج إلى الترتيب.

-- Read-only dedup of exact-duplicate rows
SELECT DISTINCT customer_id, name, signup_date
FROM customers;

التكرارات بحسب المفتاح: ROW_NUMBER

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

يحدد ORDER BY داخل النافذة أي نسخة ستكون النسخة الأساسية. اختره بعناية؛ فمثلًا يمكنك الاحتفاظ بالصف الذي حُدّث مؤخرًا.

SELECT *,
  ROW_NUMBER() OVER (
    PARTITION BY email
    ORDER BY updated_at DESC
  ) AS rn
FROM users;

اختيار النسخة الأساسية

ضع عملية الترقيم داخل CTE، واحتفظ فقط بالصفوف التي تحقق rn = 1. يعيد ذلك صفًا واحدًا لكل مفتاح، وتحديدًا الصف الذي رتّبه ORDER BY أولًا.

صيغة SELECT هذه غير مدمرة؛ فهي مثالية لإنشاء عرض نظيف أو لتغذية جدول هدف أزيلت تكراراته باستخدام INSERT ... SELECT، من دون المساس بالمصدر.

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY email ORDER BY updated_at DESC
    ) AS rn
  FROM users
)
SELECT user_id, email, name, updated_at
FROM ranked
WHERE rn = 1;

اختيار الترتيب مهم

إن ORDER BY داخل التقسيم قرار متعلق بالعمل، وليس إجراءً شكليًا:

  • يحتفظ ORDER BY updated_at DESC بالسجل الأحدث.
  • يحتفظ ORDER BY created_at ASC بالسجل الأصلي.
  • يحتفظ ORDER BY id ASC بأدنى مفتاح بديل، وهو مفيد كاختيار عشوائي ثابت.

أضف عامل كسر تعادل فريدًا كي يكون الصف المختار محددًا بشكل حتمي عندما تتساوى قيمة عمود الترتيب الأساسي أيضًا.

ROW_NUMBER() OVER (
  PARTITION BY email
  ORDER BY updated_at DESC, id ASC
) AS rn

حذف التكرارات فعليًا

لإزالة التكرارات فعليًا من الجدول، حدّد الصفوف الإضافية، أي الصفوف التي تحقق rn > 1، ثم احذفها. في Postgres وSQL Server، يمكنك الحذف باستخدام CTE؛ أما في MySQL، فمن الشائع استخدام ربط ذاتي أو استعلام فرعي.

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

WITH ranked AS (
  SELECT ctid,
    ROW_NUMBER() OVER (
      PARTITION BY email ORDER BY updated_at DESC, id ASC
    ) AS rn
  FROM users
)
DELETE FROM users
WHERE ctid IN (SELECT ctid FROM ranked WHERE rn > 1);

نمط الحذف باستخدام الربط الذاتي

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

يربط شرط الربط كل صف بصف آخر يشاركه المفتاح نفسه، لكن يملك معرّفًا أصغر؛ وأي صف له نظير بهذا المعرّف الأصغر يُعد تكرارًا ينبغي حذفه.

DELETE u1
FROM users u1
JOIN users u2
  ON u1.email = u2.email
 AND u1.id > u2.id;

قائمة التحقق من الأمان

قبل الحذف، اتخذ إجراءات تحميك:

  • ضع عملية الحذف داخل معاملة حتى تتمكن من تنفيذ ROLLBACK إذا بدا العدد غير صحيح.
  • نفّذ SELECT COUNT(*) للصفوف المطلوب حذفها أولًا، وتحقق من معقولية الناتج.
  • فكّر في إنشاء جدول نسخة احتياطية: CREATE TABLE users_bak AS SELECT * FROM users.
  • تأكد من أن أعمدة PARTITION BY تحدد التكرار فعلًا، وإلا فقد تحذف سجلات مختلفة.
BEGIN;
-- run the DELETE, inspect row count
-- COMMIT; if correct, otherwise ROLLBACK;

التكرارات شبه المطابقة والتطبيع

أحيانًا لا تكون الصفوف متساوية تمامًا، لكنها متطابقة منطقيًا: 'Ann@X.com' مقابل 'ann@x.com'، أو وجود مسافات زائدة في النهاية. استخدم تعبيرًا مطبّعًا في التقسيم بدلًا من العمود الخام.

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

ROW_NUMBER() OVER (
  PARTITION BY LOWER(TRIM(email))
  ORDER BY updated_at DESC, id ASC
) AS rn

اختبار سريع

اختر أسلوب إزالة التكرارات الآمن.

مراجعة: إزالة التكرارات بأمان

أزل التكرارات بطريقة منهجية:

  • حدّد أولًا معنى التكرار، ثم اكتشفه باستخدام GROUP BY / HAVING COUNT(*) > 1.
  • التكرارات المطابقة تمامًا → DISTINCT. التكرارات بحسب المفتاح → ROW_NUMBER مقسمة بحسب المفتاح، مع الاحتفاظ بالصفوف التي تحقق rn = 1.
  • يحدد ORDER BY الخاص بالنافذة النسخة الأساسية؛ فأضف عامل كسر تعادل فريدًا.
  • احذف الصفوف التي تحقق rn > 1 داخل معاملة، بعد معاينة العدد.
  • طبّع المفاتيح لاكتشاف التكرارات شبه المطابقة.

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

هل درس «إزالة تكرار الصفوف بأمان» مجاني؟

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

ماذا ستتعلم في «إزالة تكرار الصفوف بأمان»؟

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

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

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

كم من الوقت يستغرق درس «إزالة تكرار الصفوف بأمان»؟

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

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

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

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

  1. صفوف Top-N لكل مجموعة باستخدام ROW_NUMBER
  2. معالجة التعادلات في Top-N
  3. إزالة تكرار الصفوف بأمان
  4. الاحتفاظ بأحدث صف لكل مفتاح
← العودة إلى Coding Interview Prep