{"id":"l-sql-3-4","courseId":"sql-for-analysts","lang":"ar","kind":"lesson","summary":"ابنِ قمع تحويل (funnel) من أحداث الجلسات بالتجميع الشرطي، ثم جمّع العملاء في cohorts شهرية حسب طلبهم الأول وقِس كم منهم يعود في الأشهر اللاحقة.","html":"<p>طلبان في رأس القائمة. هدى: «ميزانية البحث المدفوع قيد المراجعة. أي مصادر الزيارات تحوّل الزيارات فعلًا إلى طلبات، وأين يتسرّب الناس؟». ورانيا: «اكتسبنا عملاء كثيرين في أشهر Black Friday. هل يعودون بالقدر نفسه الذي يعود به الآخرون؟». الأول <strong>قمع</strong> (funnel)، والثاني تحليل <strong>معدل الاحتفاظ لكل cohort</strong>. كلاهما مبني من أشياء تعرفها بالفعل: التجميع الشرطي، والتواريخ، والـ CTEs.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">قمع من أحداث الجلسات</h2>\n<p>كل صف في <code dir=\"ltr\">web_sessions</code> زيارة واحدة، مع علامات للخطوات التي بلغتها: <code dir=\"ltr\">added_to_cart</code> و<code dir=\"ltr\">purchased</code> (0 أو 1). جمع علامة قيمتها 0/1 يعدّ الجلسات التي بلغت الخطوة، فيكون القمع GROUP BY واحدًا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"sql\" data-run=\"sql\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">SQL</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"sql\" data-index=\"0\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">SELECT</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  source,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)            </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> sessions</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(added_to_cart)  </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> carts,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(purchased)      </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> purchases,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  ROUND</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(added_to_cart) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)                  </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cart_rate,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  ROUND</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(purchased) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> NULLIF</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(added_to_cart), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> checkout_rate,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  ROUND</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(purchased) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)                      </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> conversion</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> web_sessions</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> started_at </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2025-01-01'</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">GROUP BY</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> source</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ORDER BY</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> conversion </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">DESC</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>البريد الإلكتروني هو الأفضل تحويلًا إجمالًا، 10.9% من الجلسات، والإحالات هي الأسوأ بـ 7.1%. لكن معدلات الخطوات تحكي القصة الأنفع. زوّار الإحالات نادرًا ما يضيفون إلى السلة (13.3%)، لكن من يضيف منهم يتمّ الشراء أكثر من أي فئة أخرى (53.6%). والبريد الإلكتروني عكس ذلك. هاتان مشكلتان مختلفتان وإصلاحهما مختلف: الإحالات تحتاج إلى صفحات هبوط أفضل، والبريد يحتاج إلى عملية دفع أسلس.</p>\n<p>لهذا يعرض القمع <strong>معدلات الخطوات</strong>، أي كل خطوة مقسومة على السابقة، لا التحويل من البداية إلى النهاية وحده. اجعل كل مقام صريحًا في اسم العمود؛ فـ«معدل التحويل» بلا مقام هو أكثر رقم يُتجادل حوله في أي اجتماع تسويق. ويحمي <code dir=\"ltr\">NULLIF</code> القسمة لمصدر ليس فيه سلال.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تأكّد أن القمع قمع فعلًا</span></p>\n<p>كل خطوة يجب أن تكون جزءًا من الخطوة السابقة. قبل أن تُبلغ بالنتائج، شغّل <code dir=\"ltr\">SELECT COUNT(*) FROM web_sessions WHERE purchased = 1 AND added_to_cart = 0</code>. على بيانات Cartwheel النتيجة 0. لو لم تكن كذلك، لكان الشراء بلا سلة خطأً في التتبّع، وقد تتجاوز معدلات خطواتك 100%.</p>\n</aside>\n<p>استبدل <code dir=\"ltr\">source</code> بـ <code dir=\"ltr\">device</code> فيظهر اكتشاف أوضح: جلسات الحاسوب المكتبي التي تبلغ السلة تتمّ الشراء في 56% من الحالات، وجلسات الجوال في 37% فقط. والجوال يجلب أكبر قدر من الزيارات، فهذه الفجوة أثمن من أي تعديل على ميزانية الإعلانات.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ cohorts: تجميع العملاء حسب وقت بدايتهم</h2>\n<p><strong>الـ cohort</strong> مجموعة من العملاء يتشاركون فترة بداية واحدة. وهي هنا شهر أول طلب غير ملغى لهم. ثم يسأل معدل الاحتفاظ: من العملاء الذين بدأوا في الشهر M، ما نسبة من طلبوا مجددًا بعد شهر أو شهرين أو ثلاثة؟</p>\n<p>ثلاث خطوات، وثلاثة CTEs. أولًا، أعطِ كل طلب <strong>مؤشّر شهر</strong>، <code dir=\"ltr\">year * 12 + month</code>، حتى تكون فروق الأشهر عملية طرح بسيطة حتى عبر حدود السنة. ثانيًا، اعثر على الشهر الأول لكل عميل. ثالثًا، اعرض الأشهر النشطة لكل عميل نسبةً إلى الـ cohort الخاص به:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"sql\" data-run=\"sql\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">SQL</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"sql\" data-index=\"1\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WITH</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders_ok </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> customer_id, order_date,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">         CAST</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(strftime(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'%Y'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, order_date) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> INTEGER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 12</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">           +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> CAST</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(strftime(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'%m'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, order_date) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> INTEGER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_index</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  WHERE</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> status</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;></span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'cancelled'</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">firsts </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#6E7781;--shiki-dark:#8B949E\">  -- grain: one row per customer</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> customer_id,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">         MIN</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(month_index) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cohort_index,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">         strftime(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'%Y-%m'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">MIN</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(order_date)) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cohort</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders_ok</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  GROUP BY</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> customer_id</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">activity </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#6E7781;--shiki-dark:#8B949E\">  -- grain: one row per customer per active month</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT DISTINCT</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> f</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">cohort</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">f</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">cohort_index</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">o</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">customer_id</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">         o</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">month_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> f</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">cohort_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders_ok </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> o</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  JOIN</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> firsts </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> f </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ON</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> f</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">customer_id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> o</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">customer_id</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">SELECT</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  cohort,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FILTER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> customers,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  ROUND</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FILTER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        /</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FILTER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> m1_pct,</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  CASE</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> WHEN</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> MAX</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cohort_index) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2025</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 12</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 12</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> THEN</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    ROUND</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FILTER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">          /</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> COUNT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FILTER</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> month_number </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  END</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> m2_pct</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> activity</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cohort </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2025-07'</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">GROUP BY</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cohort</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ORDER BY</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cohort;</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>يحوّل الـ SELECT الأخير أرقام الأشهر إلى أعمدة باستخدام <code dir=\"ltr\">FILTER</code>. والـ <code dir=\"ltr\">DISTINCT</code> في <code dir=\"ltr\">activity</code> ضروري: معدل الاحتفاظ يعدّ <em>أشخاصًا</em>، والعميل الذي يطلب ثلاث مرات في شهر واحد عميل نشط واحد.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 720 230\" role=\"img\" aria-labelledby=\"l-sql-3-4-t1\"><defs><marker id=\"arrow-l-sql-3-4-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-sql-3-4-t1\">الـ cohorts من سبتمبر إلى ديسمبر 2025 مقابل الأشهر من 0 إلى 3. لسبتمبر الأشهر الأربعة كلها مقيسة؛ ولأكتوبر ثلاثة؛ ولنوفمبر اثنان؛ ولديسمبر الشهر 0 فقط. الخانات التي تقع بعد نهاية البيانات قيمتها غير معروفة، لا صفر.</title>\n  <text class=\"d-label-muted\" x=\"250\" y=\"30\" text-anchor=\"middle\">m0</text>\n  <text class=\"d-label-muted\" x=\"370\" y=\"30\" text-anchor=\"middle\">m1</text>\n  <text class=\"d-label-muted\" x=\"490\" y=\"30\" text-anchor=\"middle\">m2</text>\n  <text class=\"d-label-muted\" x=\"610\" y=\"30\" text-anchor=\"middle\">m3</text>\n  <text class=\"d-code\" x=\"110\" y=\"68\" text-anchor=\"middle\">2025-09</text>\n  <text class=\"d-code\" x=\"110\" y=\"113\" text-anchor=\"middle\">2025-10</text>\n  <text class=\"d-code\" x=\"110\" y=\"158\" text-anchor=\"middle\">2025-11</text>\n  <text class=\"d-code\" x=\"110\" y=\"203\" text-anchor=\"middle\">2025-12</text>\n  <rect class=\"d-box-primary\" x=\"195\" y=\"45\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"250\" y=\"68\" text-anchor=\"middle\">100%</text>\n  <rect class=\"d-box-accent\" x=\"315\" y=\"45\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"370\" y=\"68\" text-anchor=\"middle\">43.5%</text>\n  <rect class=\"d-box-accent\" x=\"435\" y=\"45\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"490\" y=\"68\" text-anchor=\"middle\">39.1%</text>\n  <rect class=\"d-box-accent\" x=\"555\" y=\"45\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"610\" y=\"68\" text-anchor=\"middle\">30.4%</text>\n  <rect class=\"d-box-primary\" x=\"195\" y=\"90\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"250\" y=\"113\" text-anchor=\"middle\">100%</text>\n  <rect class=\"d-box-accent\" x=\"315\" y=\"90\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"370\" y=\"113\" text-anchor=\"middle\">44.4%</text>\n  <rect class=\"d-box-accent\" x=\"435\" y=\"90\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"490\" y=\"113\" text-anchor=\"middle\">27.8%</text>\n  <rect class=\"d-box d-dashed\" x=\"555\" y=\"90\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"610\" y=\"113\" text-anchor=\"middle\">لم يحن بعد</text>\n  <rect class=\"d-box-primary\" x=\"195\" y=\"135\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"250\" y=\"158\" text-anchor=\"middle\">100%</text>\n  <rect class=\"d-box-accent\" x=\"315\" y=\"135\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"370\" y=\"158\" text-anchor=\"middle\">36.2%</text>\n  <rect class=\"d-box d-dashed\" x=\"435\" y=\"135\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"490\" y=\"158\" text-anchor=\"middle\">لم يحن بعد</text>\n  <rect class=\"d-box d-dashed\" x=\"555\" y=\"135\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"610\" y=\"158\" text-anchor=\"middle\">لم يحن بعد</text>\n  <rect class=\"d-box-primary\" x=\"195\" y=\"180\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-code\" x=\"250\" y=\"203\" text-anchor=\"middle\">100%</text>\n  <rect class=\"d-box d-dashed\" x=\"315\" y=\"180\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"370\" y=\"203\" text-anchor=\"middle\">لم يحن بعد</text>\n  <rect class=\"d-box d-dashed\" x=\"435\" y=\"180\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"490\" y=\"203\" text-anchor=\"middle\">لم يحن بعد</text>\n  <rect class=\"d-box d-dashed\" x=\"555\" y=\"180\" width=\"110\" height=\"36\" rx=\"6\"/>\n  <text class=\"d-label-muted\" x=\"610\" y=\"203\" text-anchor=\"middle\">لم يحن بعد</text>\n</svg><figcaption>جدول الـ cohorts مثلث: الـ cohorts الحديثة لم تعش بما يكفي لقياسها</figcaption></figure>\n<h2 id=\"sec-3\" tabindex=\"-1\">«غير معروف» ليس صفرًا</h2>\n<p>انظر إلى صف ديسمبر 2025 في نتيجة الـ query: قيمة <code dir=\"ltr\">m1_pct</code> هي 0.0. هذا ليس انقطاعًا. الشهر 1 لـ cohort ديسمبر هو يناير 2026، والبيانات تنتهي في 31 ديسمبر. يعرض العمود <code dir=\"ltr\">m2_pct</code> الإصلاح: تعبير CASE يفحص هل عاش الـ cohort ذلك الشهر (أي هل ما زال <code dir=\"ltr\">cohort_index + 2</code> داخل ديسمبر 2025) ويعيد NULL في غير ذلك. مخطط الاحتفاظ ذو الخانات الفارغة الصادقة مثلث؛ أما المخطط ذو الأصفار فيُظهر انهيارًا وهميًا في كل cohort حديث.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>عدّ الطلبات بدل العملاء</span></p>\n<p>احذف DISTINCT من <code dir=\"ltr\">activity</code>، فيضيف عميل وفيّ واحد لديه أربعة طلبات في أكتوبر 4 إلى «العملاء النشطين» في أكتوبر. فيرتفع معدل الاحتفاظ، ويتجاوز أحيانًا 100%. كلما كان المعدل عن الأشخاص، تحقّق من أن بسطه ومقامه عدّان لأشخاص كلٌّ منهم مرة واحدة، بمستوى التفصيل نفسه.</p>\n</aside>\n<p>نعود إلى سؤال رانيا. غيّر الشرط إلى 2024، فتجد أن cohort نوفمبر 2024، وهو أول جمهور Black Friday لدى Cartwheel وأكبر cohort في تلك السنة بـ 35 عميلًا، لا يحتفظ إلا بـ 14.3% في الشهر 1، وهذا أقل من معظم cohorts عام 2024. عملاء الخصومات الكبيرة يأتون عادةً من أجل الصفقة. هذه إجابة تستطيع استخدامها حين تخطّط للعرض الترويجي القادم. ويطرح التمرين سؤالًا قريب الصلة: ما نسبة من يعودون من كل cohort أصلًا خلال ثلاثة أشهر؟</p>\n<p>بهذا تكتمل أدوات التحليل. أما القسم الأخير فيدور حول الثقة: التأكد من أن البيانات والـ queries التي تكتبها تستحقها.</p>\n","toc":[{"id":"sec-1","text":"قمع من أحداث الجلسات","level":2},{"id":"sec-2","text":"الـ cohorts: تجميع العملاء حسب وقت بدايتهم","level":2},{"id":"sec-3","text":"«غير معروف» ليس صفرًا","level":2}],"takeaways":["القمع (funnel) يعدّ كم وحدة تصل إلى كل خطوة ويقسم كل خطوة على التي قبلها، فترى بالضبط أين يتسرّب الناس.","صرّح دائمًا بمقام أي معدل؛ معدل إتمام الشراء (المشتريات لكل سلة) ومعدل التحويل (المشتريات لكل جلسة) يجيبان عن سؤالين مختلفين.","الـ cohort يجمع العملاء حسب فترة حدثهم الأول، ومعدل الاحتفاظ (retention) يعدّ العملاء النشطين بعد N فترات، كلًّا مرة واحدة، مقسومًا على حجم الـ cohort.","الأشهر التي لم يعشها cohort حديث بعد قيمتها غير معروفة لا صفر؛ اعرضها NULL حتى لا يقرأها أحد على أنها انقطاع."],"further":[{"title":"SQLite aggregate functions and FILTER","url":"https://www.sqlite.org/lang_aggfunc.html"},{"title":"SQLite date and time functions","url":"https://www.sqlite.org/lang_datefunc.html"}],"quiz":[{"q":"<p>جلسات البريد الإلكتروني: 404 جلسات، و107 إضافات إلى السلة، و44 عملية شراء. أي رقم هو معدل إتمام الشراء؟</p>","options":[{"text":"10.9%، المشتريات مقسومة على الجلسات","why":"هذا معدل التحويل الإجمالي. إنه يخلط خطوتين ويخفي أين يتسرّب الناس."},{"text":"26.5%، السلال مقسومة على الجلسات","why":"هذا معدل الإضافة إلى السلة، وهو الخطوة الأولى في القمع."},{"text":"73.5%، الجلسات التي لم تُضِف إلى السلة","why":"هذا هو التسرّب عند الخطوة الأولى، وليس مقياسًا لإتمام الشراء."},{"text":"41.1%، المشتريات مقسومة على السلال","why":"صحيح. يقيس معدل إتمام الشراء الخطوة من السلة إلى الشراء، فمقامه هو السلال."}],"answer":3},{"q":"<p>لماذا يستخدم الـ query الخاص بالـ cohorts العبارة <code dir=\"ltr\">SELECT DISTINCT cohort, customer_id, month_number</code> قبل العدّ؟</p>","options":[{"text":"حتى يُحسب العميل الذي يطلب ثلاث مرات في شهر واحد عميلًا نشطًا واحدًا، لا ثلاثة.","why":"صحيح. معدل الاحتفاظ يدور حول الأشخاص. بدون DISTINCT يضخّم المشترون المتكرّرون عدد النشطين، وقد يدفعون المعدل فوق 100%."},{"text":"لأن COUNT لا يعمل بدون DISTINCT داخل CTE.","why":"COUNT يعمل في أي مكان؛ وDISTINCT هنا يتعلّق بمستوى تفصيل جدول النشاط، لا بالصياغة."},{"text":"لترتيب الـ cohorts زمنيًا.","why":"DISTINCT يزيل التكرارات؛ ولا يَعِد بأي ترتيب."}],"answer":0},{"q":"<p>يعرض cohort ديسمبر 2025 معدل احتفاظ 0% في الشهر 1. تنتهي البيانات في 2025-12-31. ماذا يجب أن يعرض الجدول؟</p>","options":[{"text":"0%، لأن أحدًا منهم لم يطلب في الشهر 1","why":"الشهر 1 لـ cohort ديسمبر هو يناير 2026، وهو غير موجود في البيانات. الصفر يدّعي أنهم انقطعوا جميعًا."},{"text":"القيمة نفسها لـ cohort نوفمبر، كتقدير.","why":"ملء الخانة بقيمة cohort آخر يخترع بيانات ويخفي أن الفترة لم تحدث بعد."},{"text":"NULL أو خانة فارغة، لأن ذلك الشهر لم يُرصد بعد.","why":"صحيح. الخانات غير المرصودة قيمتها غير معروفة. وتعبير CASE يفحص هل يقع شهر الـ cohort مضافًا إليه N داخل نطاق البيانات يجعل ذلك صريحًا."}],"answer":2},{"q":"<p>لحساب «الأشهر منذ الطلب الأول» عبر حدود السنة، لماذا تحوّل التواريخ إلى <code dir=\"ltr\">year * 12 + month</code> بدل طرح قيم <code dir=\"ltr\">strftime('%m', ...)</code>؟</p>","options":[{"text":"لأن strftime لا تستطيع إعادة الشهر.","why":"تستطيع، باستخدام ‘%m’. المشكلة فيما يحدث حين تطرح أشهرًا من سنوات مختلفة."},{"text":"بين ديسمبر 2024 ويناير 2025 شهر واحد، لكن 1 - 12 تعطي ‎-11؛ ومؤشّر شهر واحد يجعل الفرق صحيحًا.","why":"صحيح. تحويل كل شهر إلى رقم واحد متزايد يجعل فروق الأشهر عملية طرح بسيطة، عبر أي حدود بين السنوات."},{"text":"لأنه أسرع في الحساب.","why":"السرعة ليست المشكلة؛ طرح أرقام الأشهر المجرّدة خاطئ عبر السنوات."}],"answer":1}],"exercise":{"kind":"sql","starter":"-- Share of each 2025 cohort that ordered again within 3 months\nWITH orders_ok AS (\n  SELECT customer_id,\n         order_date,\n         CAST(strftime('%Y', order_date) AS INTEGER) * 12\n           + CAST(strftime('%m', order_date) AS INTEGER) AS month_index\n  FROM orders\n  WHERE status <> 'cancelled'\n),\nfirsts AS (\n  SELECT customer_id,\n         MIN(month_index) AS cohort_index,\n         strftime('%Y-%m', MIN(order_date)) AS cohort\n  FROM orders_ok\n  GROUP BY customer_id\n),\nactivity AS (\n  SELECT f.cohort, o.customer_id, o.month_index - f.cohort_index AS month_number\n  FROM orders_ok AS o\n  JOIN firsts AS f ON f.customer_id = o.customer_id\n)\nSELECT\n  cohort,\n  COUNT(*) AS customers,\n  ROUND(100.0 * COUNT(*) FILTER (WHERE month_number BETWEEN 1 AND 3)\n        / COUNT(*), 1) AS repeat_3m_pct\nFROM activity\nWHERE cohort BETWEEN '2025-01' AND '2025-09'\nGROUP BY cohort\nORDER BY cohort;","solution":"WITH orders_ok AS (\n  SELECT customer_id,\n         order_date,\n         CAST(strftime('%Y', order_date) AS INTEGER) * 12\n           + CAST(strftime('%m', order_date) AS INTEGER) AS month_index\n  FROM orders\n  WHERE status <> 'cancelled'\n),\nfirsts AS (\n  SELECT customer_id,\n         MIN(month_index) AS cohort_index,\n         strftime('%Y-%m', MIN(order_date)) AS cohort\n  FROM orders_ok\n  GROUP BY customer_id\n),\nactivity AS (\n  SELECT f.cohort, o.customer_id, o.month_index - f.cohort_index AS month_number\n  FROM orders_ok AS o\n  JOIN firsts AS f ON f.customer_id = o.customer_id\n)\nSELECT\n  cohort,\n  COUNT(DISTINCT customer_id) AS customers,\n  ROUND(100.0 * COUNT(DISTINCT customer_id) FILTER (WHERE month_number BETWEEN 1 AND 3)\n        / COUNT(DISTINCT customer_id), 1) AS repeat_3m_pct\nFROM activity\nWHERE cohort BETWEEN '2025-01' AND '2025-09'\nGROUP BY cohort\nORDER BY cohort;","orderMatters":true,"title":"معدل تكرار الشراء خلال ثلاثة أشهر لكل cohort","prompt":"<p>تريد رانيا رقمًا واحدًا لكل cohort: من العملاء الذين كان <strong>طلبهم الأول</strong> في شهر معيّن، ما النسبة المئوية لمن طلبوا مجددًا <strong>في أي من الأشهر الثلاثة التالية</strong> (أرقام الأشهر 1 أو 2 أو 3)؟</p>\n<p>أعِد <code dir=\"ltr\">cohort</code> (‘YYYY-MM’) و<code dir=\"ltr\">customers</code> (حجم الـ cohort) و<code dir=\"ltr\">repeat_3m_pct</code> (مقرّبًا إلى منزلة عشرية واحدة) للـ cohorts من 2025-01 إلى 2025-09، وهي التي رُصدت أشهرها الثلاثة كلها. رتّب حسب <code dir=\"ltr\">cohort</code>. الترتيب مهم.</p>\n<p>الـ CTEs صحيحة. أما الـ SELECT الأخير فيعدّ الشيء الخطأ.</p>\n","hints":["ما مستوى التفصيل في <code dir=\"ltr\">activity</code>؟ صف واحد لكل طلب، فالعميل الذي لديه خمسة طلبات يظهر خمس مرات.","حجم الـ cohort وعدد العائدين كلاهما عن الأشخاص. اعدد <code dir=\"ltr\">DISTINCT customer_id</code> لا الصفوف.","<code dir=\"ltr\">COUNT(DISTINCT customer_id) FILTER (WHERE month_number BETWEEN 1 AND 3)</code> يعدّ كل عميل عائد مرة واحدة، مهما كان عدد طلباته."],"explanation":"<p>في <code dir=\"ltr\">activity</code> صف واحد لكل طلب، فعدّ <code dir=\"ltr\">COUNT(*)</code> الطلبات: تضخّم حجم الـ cohort لأنه شمل كل طلب قدّمه عملاؤه في أي وقت، وحُسب العميل الذي طلب في الأشهر 1 و2 و3 ثلاث مرات في البسط. عدّ العملاء دون تكرار في الموضعين يضع البسط والمقام بمستوى التفصيل نفسه، أي الأشخاص. تتراوح معدلات التكرار بين نحو 31% (فبراير) و67% (يونيو)؛ ومع cohorts فيها بين 16 و29 عميلًا، يحرّك فرق شخص أو شخصين المعدل عدة نقاط، فاعرض حجم الـ cohort بجانبه.</p>\n","checkLabels":{}},"words":648,"readMinutes":4}