0Pricing
Coding Interview Prep · درس

الاحتفاظ في اليوم N والاحتفاظ المتحرك

الفرق بين تعريفات الاحتفاظ الكلاسيكي والمتحرك والمقيّد

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

لماذا للاحتفاظ تعريفات متعددة

نادرًا ما سيقول المحاوِر فقط: "احسب الاحتفاظ". والسؤال المتابع الدقيق هو: أي احتفاظ تقصد؟ فالبيانات نفسها تنتج أرقامًا مختلفة جدًا بحسب التعريف.

التعريفات الثلاثة التي يجب أن تعرفها هي: الاحتفاظ في اليوم N (الكلاسيكي)، والاحتفاظ المتحرك (غير المحدود)، والاحتفاظ ضمن نافذة محددة. إن فهم الفرق بينها، وسؤالك عن التعريف الذي يريده النشاط التجاري، هو بحد ذاته المهارة التي يجري اختبارها.

الاحتفاظ في اليوم N (الكلاسيكي)

يسأل الاحتفاظ في اليوم N: هل كان المستخدم نشطًا في اليوم N تمامًا بعد أول إجراء له؟ يُعدّ الاحتفاظ في اليوم 1 واليوم 7 واليوم 30 من المقاييس الأساسية لتطبيقات الهاتف المحمول.

الكلمة المحورية هي تمامًا. فالمستخدم الذي كان نشطًا في اليوم 6 واليوم 8، لكنه لم يكن نشطًا في اليوم 7، لا يُعدّ محتفَظًا به في اليوم 7 وفق التعريف الكلاسيكي. وهذه الدقة هي ما يجعل العدد صارمًا والمنحنى متعرجًا.

حساب الفرق بين اليومين

يعتمد الاحتفاظ في اليوم N على عدد الأيام بين بداية الفوج وكل يوم نشاط. في Postgres، يؤدي طرح تاريخين إلى الحصول مباشرةً على عدد صحيح يمثل عدد الأيام.

أما اللهجات الأخرى فتستخدم: DATEDIFF(day, start, d) في SQL Server، وDATEDIFF(d, start) في MySQL. اذكر اللهجة التي تستخدمها؛ فالمفهوم، أي إزاحة الأيام، واحد.

WITH cohort AS (
  SELECT user_id, MIN(event_at::date) AS day0
  FROM events GROUP BY user_id
),
act AS (
  SELECT DISTINCT user_id, event_at::date AS day
  FROM events
)
SELECT c.user_id, (a.day - c.day0) AS day_n
FROM cohort c
JOIN act a ON a.user_id = c.user_id;

استعلام الاحتفاظ في اليوم 7

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

المساواة = 7، وليس >= 7، هي العلامة المميزة للاحتفاظ الكلاسيكي. فاستبدالها بمتباينة يغيّر التعريف بصمت.

WITH dn AS (
  SELECT c.user_id, (a.day - c.day0) AS day_n
  FROM cohort c JOIN act a ON a.user_id = c.user_id
)
SELECT
  COUNT(DISTINCT CASE WHEN day_n = 7 THEN user_id END) AS d7_retained,
  COUNT(DISTINCT user_id)                               AS cohort_size,
  ROUND(100.0 * COUNT(DISTINCT CASE WHEN day_n = 7 THEN user_id END)
        / NULLIF(COUNT(DISTINCT user_id), 0), 1)         AS d7_pct
FROM dn;

الاحتفاظ المتحرك (غير المحدود)

يطرح الاحتفاظ المتحرك عند اليوم N سؤالًا أقل صرامة: هل كان المستخدم نشطًا في اليوم N أو في أي يوم بعده؟ فهو يعدّ المستخدم محتفَظًا به في اليوم 7 إذا عاد في اليوم 7 أو اليوم 20 أو في أي وقت لاحق.

ينتج عن ذلك منحنى أكثر سلاسة وارتفاعًا، وغالبًا ما يُفضّل لقياس التعلّق طويل الأمد. ويتمثل التغيير المميز في الانتقال من = N إلى >= N في آخر يوم نشاط.

الاحتفاظ المتحرك باستخدام MAX لليوم

الطريقة الواضحة لحساب الاحتفاظ المتحرك هي العثور على آخر إزاحة ليوم نشاط لكل مستخدم باستخدام MAX، ثم اعتبار المستخدم محتفَظًا به عند اليوم N إذا كانت هذه القيمة العظمى >= N.

بعد حساب MAX، يصبح لكل مستخدم صف واحد، ولذلك يكون العد بسيطًا. كما يوضح ذلك أن الاحتفاظ المتحرك رتيب: فإذا كان المستخدم محتفَظًا به في اليوم 30، فهو محتفَظ به في كل قيمة أصغر من N.

WITH last_day AS (
  SELECT c.user_id, MAX(a.day - c.day0) AS max_day_n
  FROM cohort c JOIN act a ON a.user_id = c.user_id
  GROUP BY c.user_id
)
SELECT
  COUNT(*)                                          AS cohort_size,
  COUNT(*) FILTER (WHERE max_day_n >= 7)            AS rolling_d7,
  ROUND(100.0 * COUNT(*) FILTER (WHERE max_day_n >= 7)
        / NULLIF(COUNT(*), 0), 1)                    AS rolling_d7_pct
FROM last_day;

الاحتفاظ ضمن نافذة محددة

الحل الوسط هو الاحتفاظ ضمن نافذة محددة: أن يكون المستخدم نشطًا مرة واحدة على الأقل ضمن نافذة حول اليوم N، مثل الأيام من 5 إلى 9 لقياس "الأسبوع 1". وهذا يسمح بالمستخدمين غير النشطين في اليوم المحدد تمامًا، لكنه يقدّم تنعيمًا أقل من الاحتفاظ المتحرك بالكامل.

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

SELECT
  COUNT(DISTINCT CASE WHEN day_n BETWEEN 5 AND 9
                      THEN user_id END) AS week1_retained,
  COUNT(DISTINCT user_id)               AS cohort_size
FROM dn;

ثلاثة تعريفات للمستخدم نفسه

لنجعل الفرق واضحًا. يبدأ أحد المستخدمين في اليوم 0، ثم يكون نشطًا في اليوم 9 فقط.

  • اليوم 7 الكلاسيكي: غير محتفَظ به، إذ لم يكن نشطًا في اليوم 7 تحديدًا.
  • اليوم 7 المتحرك: محتفَظ به، لأن الحد الأقصى لليوم هو 9 >= 7.
  • الأسبوع 1 ضمن نافذة 5–9: محتفَظ به، لأن اليوم 9 يقع ضمن النافذة.

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

دقة الفترة: يوم مقابل أسبوع مقابل شهر

يمكن تعميم مفهوم "اليوم N" إلى الفترة N. ففي منتج موجّه للشركات ويُستخدم شهريًا، يكون الاحتفاظ اليومي ضجيجًا؛ لذا ستجمع البيانات حسب الشهر وتسأل عن الشهر N. والآلية واحدة، ولا يتغير سوى مستوى دقة التقريب.

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

-- weekly grain: offset in whole weeks
SELECT
  c.user_id,
  FLOOR((a.day - c.day0) / 7) AS week_n
FROM cohort c
JOIN act a ON a.user_id = c.user_id;

فخ البقاء ونضج الفوج

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

احمِ الاستعلام بإدراج الأفواج التي يبلغ عمرها >= N فقط عند إعداد تقرير اليوم N. استخدم التصفية على CURRENT_DATE - day0 >= N. فنسيان ذلك يجعل الأفواج الحديثة تبدو سيئة بصورة كارثية.

WITH cohort AS (
  SELECT user_id, MIN(event_at::date) AS day0
  FROM events GROUP BY user_id
)
SELECT *
FROM cohort
WHERE (CURRENT_DATE - day0) >= 30;  -- mature enough for Day-30

اختيار التعريف بصوت واضح

أفضل إجابة في المقابلة ليست استعلامًا، بل سؤالًا تطرحه بدورك: «هل تريد الاحتفاظ الكلاسيكي في اليوم N، أم الاحتفاظ المتحرك، أم نافذة محددة؟ وما الفترة الطبيعية؟»

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

اختبار سريع

يحدث أول إجراء للمستخدم في اليوم 0، ويكون نشاطه الآخر الوحيد في اليوم 12. وفق كل تعريف، هل يُعدّ محتفَظًا به في اليوم 7؟

مراجعة: تعريفات الاحتفاظ

أهم ما يتعلق بالاحتفاظ في اليوم N والاحتفاظ المتحرك:

  • الاحتفاظ الكلاسيكي في اليوم N: نشاط في اليوم N تحديدًا (الإزاحة = N) — منحنى صارم ومتعرج.
  • الاحتفاظ المتحرك: نشاط في اليوم N أو بعده (MAX offset >= N) — منحنى أكثر سلاسة ورتابة، ويقيس التعلّق.
  • الاحتفاظ ضمن نافذة محددة: نشاط ضمن نافذة (BETWEEN) — الحل الوسط الواقعي.
  • عمّم اليوم ليصبح أي مستوى دقة للفترة يطابق وتيرة استخدام المنتج.
  • أعد تقارير اليوم N للأفواج الناضجة فقط (العمر >= N) لتجنّب فخ البقاء، واسأل دائمًا عن التعريف الذي يقصده النشاط التجاري.

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

هل درس «الاحتفاظ في اليوم N والاحتفاظ المتحرك» مجاني؟

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

ماذا ستتعلم في «الاحتفاظ في اليوم N والاحتفاظ المتحرك»؟

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

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

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

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

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

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

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

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

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