0Pricing
SQL Interview Prep · درس

عدد N من الصفوف المتتالية التي تستوفي شرطًا

نمط النافذة الكلاسيكي: «ثلاثة أيام متتالية تتجاوز فيها المبيعات القيمة X»

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

مسألة كلاسيكية في LeetCode

هذه إحدى أكثر مسائل مقابلات SQL شيوعًا: «اعثر على جميع التواريخ التي تحتوي على ثلاثة أيام متتالية على الأقل تجاوزت فيها المبيعات حدًا معينًا»، أو مسألة LeetCode المفضلة: «اعرض الملعب الذي يحتوي على 3 صفوف متتالية أو أكثر تجاوز فيها الحضور 100».

البنية واحدة دائمًا: لا يُعدّ الصف مستوفيًا للشرط إلا إذا كان جزءًا من سلسلة تضم N من الصفوف المتتالية المستوفية للشرط. يوضّح هذا الدرس حلّين واضحين والفخ الذي يوقع معظم المرشحين.

بيانات العينة

سنستخدم جدول sales يوميًا. والشرط هو amount > 100. يجب أن نعيد كل يوم ينتمي إلى سلسلة من 3 أيام تقويمية متتالية أو أكثر، وتستوفي جميعها الشرط.

  • sale_date — صف واحد لكل يوم
  • amount — إجمالي المبيعات في ذلك اليوم

التفصيل المهم: يجب أن تكون الصفوف متتالية في التسلسل، وفي الإصدارات المعتمدة على التواريخ يجب أن تكون متتالية في التقويم أيضًا.

SELECT * FROM sales ORDER BY sale_date;
-- sale_date  | amount
-- 2024-03-01 |  120
-- 2024-03-02 |  150
-- 2024-03-03 |  130
-- 2024-03-04 |   90
-- 2024-03-05 |  200

النهج 1: التصفية ثم إنشاء الجزر

النهج المتين هو: الاحتفاظ أولًا بالصفوف المستوفية للشرط فقط، ثم تجميع الصفوف المتبقية في جزر متتالية، ثم الاحتفاظ بالجزر التي يبلغ طولها N على الأقل.

الخطوة الأولى هي التصفية باستخدام WHERE. وفي الخطوة الثانية نعيد استخدام مرساة الفجوات والجزر. وبما أننا صفّينا أولًا، فإن الجزيرة هنا تعني «سلسلة من الأيام المتتالية المستوفية للشرط».

WITH qualifying AS (
  SELECT sale_date
  FROM sales
  WHERE amount > 100
)
SELECT * FROM qualifying ORDER BY sale_date;

تثبيت سلاسل الصفوف المستوفية للشرط

رقّم الصفوف المستوفية للشرط حسب التاريخ، ثم اطرح الرقم للحصول على مرساة الجزيرة. ستشترك الصفوف المتتالية في التقويم والمستوفية للشرط جميعًا في المرساة نفسها؛ أما أي يوم غير مستوفٍ للشرط فقد أُزيل، مما يقطع السلسلة في الموضع الصحيح تمامًا.

WITH qualifying AS (
  SELECT sale_date
  FROM sales
  WHERE amount > 100
),
numbered AS (
  SELECT sale_date,
    ROW_NUMBER() OVER (ORDER BY sale_date) AS rn
  FROM qualifying
)
SELECT sale_date, sale_date - rn AS grp
FROM numbered;

الاحتفاظ بالجزر الطويلة بما يكفي

جمّع حسب المرساة، واحسب عدد الصفوف، واحتفظ فقط بالمجموعات التي تحقق COUNT(*) >= 3. إذا أراد المحاور إعادة التواريخ الفردية المستوفية للشرط، فاربط المراسي المحتفظ بها بالصفوف المرقّمة.

WITH qualifying AS (
  SELECT sale_date FROM sales WHERE amount > 100
),
numbered AS (
  SELECT sale_date,
    ROW_NUMBER() OVER (ORDER BY sale_date) AS rn
  FROM qualifying
),
islands AS (
  SELECT sale_date - rn AS grp, COUNT(*) AS len
  FROM numbered
  GROUP BY sale_date - rn
  HAVING COUNT(*) >= 3
)
SELECT n.sale_date
FROM numbered n
JOIN islands i ON n.sale_date - n.rn = i.grp
ORDER BY n.sale_date;

النهج 2: نافذة COUNT المنزلقة

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

أضف أولًا علامة منطقية، ثم اجمع هذه العلامة عبر إطارات منزلقة.

SELECT sale_date, amount,
  CASE WHEN amount > 100 THEN 1 ELSE 0 END AS ok
FROM sales;

الجمع عبر ثلاثة إطارات

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

هذه هي التقنية التي يعتمد عليها حل LeetCode 601 (Human Traffic of Stadium).

WITH flagged AS (
  SELECT sale_date, amount,
    CASE WHEN amount > 100 THEN 1 ELSE 0 END AS ok
  FROM sales
),
w AS (
  SELECT *,
    SUM(ok) OVER (ORDER BY sale_date
      ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS s_end,
    SUM(ok) OVER (ORDER BY sale_date
      ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS s_mid,
    SUM(ok) OVER (ORDER BY sale_date
      ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) AS s_start
  FROM flagged
)
SELECT sale_date, amount
FROM w
WHERE ok = 1 AND (s_end = 3 OR s_mid = 3 OR s_start = 3);

فخ فجوات التقويم

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

الدرس: طبّق النافذة المنزلقة على السلسلة اليومية الكاملة (ولا تُجرِ التصفية المسبقة)، أو استخدم طريقة مرساة التاريخ التي تراعي فجوات التقويم بطبيعتها. اذكر هذه المفاضلة في المقابلة.

التعميم لأي قيمة N

يتعمّم النهج 1 (التصفية ثم إنشاء الجزر) بسهولة: غيّر فقط HAVING COUNT(*) >= N. وهذه ميزته الكبرى مقارنةً بمجموع النوافذ المتعددة، الذي يحتاج إلى إطارات أكثر كلما زادت N.

عند استخدام N كمعامل أو عندما تكون كبيرة، يُفضّل استخدام طريقة الجزر — فهي تتطلب تغيير حد واحد بدلًا من كتابة N−1 من النوافذ يدويًا.

-- only the threshold changes for N = 5
HAVING COUNT(*) >= 5

اختيار النهج

دليل سريع يمكنك قوله بصوت عالٍ:

  • التصفية ثم إنشاء الجزر: يراعي فجوات التقويم، ويتعمّم لأي قيمة N، ويعيد السلاسل الكاملة — وهو الخيار الافتراضي الآمن.
  • مجموع النافذة المنزلقة: أنيق عند استخدام قيمة N صغيرة وثابتة على سلسلة يومية كثيفة، لكن انتبه إلى فخ الفرق بين ROWS والتقويم.

إن تسمية النهجين مع تبرير اختيارك هو بالضبط ما يقدّره المحاورون في المستويين المتوسط والمتقدم.

الحل الكامل

الإجابة القابلة للنقل، لأي قيمة N، التي تراعي التتالي في التقويم وتعيد التواريخ المستوفية للشرط:

WITH qualifying AS (
  SELECT sale_date FROM sales WHERE amount > 100
),
numbered AS (
  SELECT sale_date,
    ROW_NUMBER() OVER (ORDER BY sale_date) AS rn
  FROM qualifying
),
islands AS (
  SELECT sale_date - rn AS grp, COUNT(*) AS len
  FROM numbered
  GROUP BY sale_date - rn
  HAVING COUNT(*) >= 3
)
SELECT n.sale_date
FROM numbered n
JOIN islands i ON n.sale_date - n.rn = i.grp
ORDER BY n.sale_date;

تحقّق سريع

اكتشف الخطأ الدقيق.

مراجعة

بالنسبة إلى N من الصفوف المتتالية التي تستوفي شرطًا:

  • التصفية ثم إنشاء الجزر: احتفظ بالصفوف المستوفية للشرط، وثبّت المرساة باستخدام date - ROW_NUMBER()، ثم جمّع واستخدم HAVING COUNT(*) >= N. يتعمّم هذا النهج ويراعي فجوات التقويم.
  • مجموع النافذة المنزلقة: ضع علامة على الصفوف، واجمعها عبر إطارات ثابتة من N صفوف؛ وهو أنيق، لكن احذر الفرق بين ROWS والتقويم عند استخدام بيانات جرت تصفيتها مسبقًا.

التالي: حساب سلسلة نشاط المستخدم الحالية حتى تاريخ اليوم.

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

هل درس «عدد N من الصفوف المتتالية التي تستوفي شرطًا» مجاني؟

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

ماذا ستتعلم في «عدد N من الصفوف المتتالية التي تستوفي شرطًا»؟

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

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

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

كم من الوقت يستغرق درس «عدد N من الصفوف المتتالية التي تستوفي شرطًا»؟

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

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

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

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

  1. اكتشاف الأيام التقويمية المتتالية
  2. أطول سلسلة متتالية لكل مستخدم
  3. عدد N من الصفوف المتتالية التي تستوفي شرطًا
  4. السلسلة النشطة الحالية حتى اليوم
← العودة إلى SQL Interview Prep