{"id":"l-sql-3-1","courseId":"sql-for-analysts","lang":"ar","kind":"lesson","summary":"استخدم الـ scalar subqueries والجداول المشتقة والـ subqueries المترابطة حيث تناسب، وأعِد بناء الـ queries الطويلة في خطوات CTE مسمّاة، وتتبّع التسلسلات الهرمية بأي عمق بـ CTE تكراري.","html":"<p>يطرح كريم سؤالًا يخفي في داخله سؤالًا ثانيًا: «أي العملاء أنفقوا أكثر من العميل المتوسط في 2025؟». للإجابة تحتاج إلى المتوسط أولًا، وهذا بدوره يحتاج إلى الإيراد لكل عميل. إنها ثلاث خطوات: الإيراد لكل عميل، ثم متوسطه، ثم المقارنة. يعطيك SQL طريقتين لتداخل الخطوات، الـ subqueries والـ CTEs، والاختيار بينهما يحدّد هل يستطيع المحلّل التالي أن يقرأ عملك.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">ثلاثة أنواع من الـ subqueries</h2>\n<p>استخدمت اثنين منها بالفعل. <strong>الجدول المشتق</strong> subquery داخل FROM يتصرّف كجدول (الإيراد لكل طلب الذي أصلح الـ fan-out). و<strong>الـ subquery المترابط</strong> يشير إلى الصف الخارجي ويعمل لكل صف (الـ anti-join بـ NOT EXISTS). والثالث هو <strong>الـ scalar subquery</strong>: query يعيد قيمة واحدة بالضبط، ويمكن استخدامه في أي مكان تصلح فيه قيمة.</p>\n<p>هذا سؤال كريم مكتوبًا بالتداخل وحده:</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 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:#1F2328;--shiki-dark:#E6EDF3\"> above_average_customers</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</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:#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 style=\"color:#0550AE;--shiki-dark:#79C0FF\">SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">quantity</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">unit_price</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:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">discount</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\"> revenue</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 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\"> order_items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> oi </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ON</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">order_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\">order_id</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  WHERE</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\">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:#CF222E;--shiki-dark:#FF7B72\">    AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> >=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2025-01-01'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2026-01-01'</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  GROUP BY</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 style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> r</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">WHERE</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> r</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">revenue</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ></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:#0550AE;--shiki-dark:#79C0FF\"> AVG</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(revenue) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</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:#0550AE;--shiki-dark:#79C0FF\"> SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">quantity</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">unit_price</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:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">discount</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\"> revenue</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 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\"> order_items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> oi </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ON</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">order_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\">order_id</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    WHERE</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\">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:#CF222E;--shiki-dark:#FF7B72\">      AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> >=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2025-01-01'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2026-01-01'</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    GROUP BY</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:#1F2328;--shiki-dark:#E6EDF3\">);</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>إنه يعمل: 140 عميلًا. لكنه صعب القراءة أيضًا، ومنطق الإيراد مكتوب فيه مرتين. حين يغيّر أحدهم تعريف الإيراد في الربع القادم، سيحدّث نسخة وينسى الأخرى.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">التحليل نفسه بالـ CTEs</h2>\n<p><strong>الـ CTE</strong> (common table expression) يسمّي query باستخدام <code dir=\"ltr\">WITH name AS (...)</code>، وتشير إليه الخطوات اللاحقة كما تشير إلى جدول:</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\"> revenue_2025 </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 who bought in 2025</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT</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\">         SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">quantity</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">unit_price</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:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">discount</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\"> revenue</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 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\"> order_items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> oi </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ON</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> oi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">order_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\">order_id</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  WHERE</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\">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:#CF222E;--shiki-dark:#FF7B72\">    AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> >=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2025-01-01'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AND</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\">order_date</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> '2026-01-01'</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  GROUP BY</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:#1F2328;--shiki-dark:#E6EDF3\">benchmark </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:#0550AE;--shiki-dark:#79C0FF\"> AVG</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(revenue) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> avg_revenue </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> revenue_2025</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:#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:#1F2328;--shiki-dark:#E6EDF3\"> buyers,</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  SUM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">r</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">revenue</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> b</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">avg_revenue</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\"> above_average,</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\">b</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">avg_revenue</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</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\"> avg_revenue</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> revenue_2025 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> r</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">CROSS JOIN</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> benchmark </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> b;</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>الآن يُقرأ التحليل كالجملة التي يجيب عنها: الإيراد لكل عميل، ثم المعيار، ثم المقارنة. الإيراد معرّف مرة واحدة. وأثناء البناء يمكنك استبدال الـ SELECT الأخير بـ <code dir=\"ltr\">SELECT * FROM revenue_2025 LIMIT 5</code> لتفحص أي خطوة، وهذه أفضل عادة منفردة لتصحيح الـ SQL الطويل. والـ <code dir=\"ltr\">CROSS JOIN</code> آمن هنا لأن في <code dir=\"ltr\">benchmark</code> صفًا واحدًا بالضبط. في SQLite تكون المقارنة 1 أو 0، فيعدّ <code dir=\"ltr\">SUM(condition)</code> الصفوف التي قيمتها TRUE؛ وفي PostgreSQL ستكتب <code dir=\"ltr\">COUNT(*) FILTER (WHERE ...)</code>.</p>\n<p>إذن 140 من أصل 418 مشتريًا يقعون فوق المتوسط البالغ 781.84. هذا معتاد في بيانات الإيرادات: أقلية من العملاء الكبار ترفع المتوسط، ولهذا ستعرض الوسيط بجانبه في كثير من الأحيان.</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>subquery أم CTE؟</span></p>\n<p>استخدم الـ subquery لشيء صغير ومحلي، مثل <code dir=\"ltr\">IN (SELECT ...)</code> أو قيمة مفردة واحدة. واستخدم الـ CTE حالما تستحق الخطوة اسمًا، أو تُستخدم مرتين، أو تتجاوز بضعة أسطر. نادرًا ما يكون الأداء هو العامل الحاسم: SQLite وPostgreSQL كلاهما يدمج الـ CTEs عادةً ويخطّط لها كما يخطّط للـ subqueries.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">الـ CTE التكراري: تتبّع تسلسل هرمي</h2>\n<p>يعود طلب رانيا الخاص بإعادة الهيكلة: «اعرض كل من في فريق الهندسة الذي يقوده بيتر ويبر، على أي مستوى، مع بُعد كل شخص عنه». الـ self-join يعطيك مستوى واحدًا. فريق بيتر فيه مستويان، وقد يكون في قسم آخر خمسة. <strong>الـ CTE التكراري</strong> يتعمّق بقدر ما تتعمّق البيانات:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"sql\" data-run=\"sql\" data-index=\"2\"><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=\"2\" 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:#CF222E;--shiki-dark:#FF7B72\"> RECURSIVE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> org </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\">  -- anchor: where the walk starts</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> employee_id, first_name, title, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> depth, first_name </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> path</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> employees</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  WHERE</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> employee_id </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 4</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  UNION ALL</span></span>\n<span class=\"line\"><span style=\"color:#6E7781;--shiki-dark:#8B949E\">  -- recursive step: people who report to anyone found so far</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  SELECT</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">employee_id</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">first_name</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">org</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">depth</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:#0550AE;--shiki-dark:#79C0FF\">         org</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">path</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ||</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> ' > '</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ||</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">first_name</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> employees </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">AS</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> e</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  JOIN</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> org </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ON</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">manager_id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> org</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">employee_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 style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> depth, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">path</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, title</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">FROM</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> org</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ORDER BY</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> path</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p>البنية هي نفسها دائمًا. <strong>query الارتكاز</strong> يعمل مرة واحدة وينتج صفوف البداية. و<strong>الـ query التكراري</strong> يربط <code dir=\"ltr\">employees</code> بـ <code dir=\"ltr\">org</code> نفسه، لكنه في كل تكرار لا يرى إلا الصفوف التي أضافها التكرار السابق. كل جولة تضيف المستوى التالي نزولًا، وينتهي التتبّع حين لا يجد تكرارٌ أحدًا.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 720 220\" role=\"img\" aria-labelledby=\"l-sql-3-1-t1\"><defs><marker id=\"arrow-l-sql-3-1-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-1-t1\">التكرار 0 هو الارتكاز، بيتر. التكرار 1 يضيف من يتبعون له مباشرةً، فيليكس وآيفي. التكرار 2 يضيف من يتبعون لفيليكس: سلمى ورايان ومنى ودانيال. التكرار 3 لا يجد أحدًا، فيتوقف التكرار.</title>\n  <text class=\"d-label-muted\" x=\"70\" y=\"45\" text-anchor=\"middle\">التكرار 0</text>\n  <text class=\"d-label-muted\" x=\"70\" y=\"105\" text-anchor=\"middle\">التكرار 1</text>\n  <text class=\"d-label-muted\" x=\"70\" y=\"165\" text-anchor=\"middle\">التكرار 2</text>\n  <text class=\"d-label-muted\" x=\"70\" y=\"210\" text-anchor=\"middle\">التكرار 3</text>\n  <rect class=\"d-box-primary\" x=\"330\" y=\"22\" width=\"120\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label-strong\" x=\"390\" y=\"45\" text-anchor=\"middle\">Peter</text>\n  <rect class=\"d-box-accent\" x=\"230\" y=\"82\" width=\"120\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"290\" y=\"105\" text-anchor=\"middle\">Felix</text>\n  <rect class=\"d-box-accent\" x=\"470\" y=\"82\" width=\"120\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"530\" y=\"105\" text-anchor=\"middle\">Ivy</text>\n  <rect class=\"d-box\" x=\"140\" y=\"142\" width=\"100\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"190\" y=\"165\" text-anchor=\"middle\">Salma</text>\n  <rect class=\"d-box\" x=\"250\" y=\"142\" width=\"100\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"300\" y=\"165\" text-anchor=\"middle\">Ryan</text>\n  <rect class=\"d-box\" x=\"360\" y=\"142\" width=\"100\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"410\" y=\"165\" text-anchor=\"middle\">Mona</text>\n  <rect class=\"d-box\" x=\"470\" y=\"142\" width=\"100\" height=\"36\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"520\" y=\"165\" text-anchor=\"middle\">Daniel</text>\n  <text class=\"d-label-muted\" x=\"390\" y=\"210\" text-anchor=\"middle\">لا صفوف جديدة، فيتوقف التكرار</text>\n  <path class=\"d-line\" d=\"M370 58 L300 82\"/>\n  <path class=\"d-line\" d=\"M410 58 L520 82\"/>\n  <path class=\"d-line\" d=\"M270 118 L190 142\"/>\n  <path class=\"d-line\" d=\"M285 118 L300 142\"/>\n  <path class=\"d-line\" d=\"M300 118 L410 142\"/>\n  <path class=\"d-line\" d=\"M320 118 L520 142\"/>\n</svg><figcaption>كل تكرار في الـ CTE التكراري يضيف المستوى التالي من الهيكل التنظيمي</figcaption></figure>\n<p>يُمرَّر <code dir=\"ltr\">depth</code> و<code dir=\"ltr\">path</code> عبر التكرار: كل صف جديد يحسب قيمه من الصف الأب الذي ارتبط به. والترتيب حسب <code dir=\"ltr\">path</code> يطبع النتيجة كشجرة متدرّجة. يصلح النمط نفسه لتجميع التكاليف صعودًا في شجرة فئات، أو لتتبّع سلاسل الإحالة، أو لتفكيك قائمة مكوّنات منتج.</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>إذا احتوت البيانات على حلقة (A يدير B، وB يدير A، بعد استيراد سيئ)، فلن تنفد الصفوف أمام التكرار أبدًا، وسيعمل الـ query حتى يفشل أو يوقفه أحد. حين لا تثق تمامًا بتسلسل هرمي، أضف <code dir=\"ltr\">WHERE org.depth &lt; 20</code> إلى الخطوة التكرارية. استخدام <code dir=\"ltr\">UNION</code> بدل <code dir=\"ltr\">UNION ALL</code> يمنع أيضًا تكرار الصفوف المتطابقة تمامًا، لكن وجود عمود للعمق أو للمسار يُبطل ذلك، فيبقى حدّ العمق هو الحارس الذي يُعتمد عليه.</p>\n</aside>\n<p>بالـ CTEs تستطيع أن تسمّي كل خطوة. يضيف الدرس التالي أداة تتيح لكل صف أن يرى جيرانه دون ضغط أي شيء: دوال النافذة.</p>\n","toc":[{"id":"sec-1","text":"ثلاثة أنواع من الـ subqueries","level":2},{"id":"sec-2","text":"التحليل نفسه بالـ CTEs","level":2},{"id":"sec-3","text":"الـ CTE التكراري: تتبّع تسلسل هرمي","level":2}],"takeaways":["الـ scalar subquery يعيد قيمة واحدة ويمكن وضعه في أي مكان تصلح فيه قيمة، مثل المقارنة بمتوسط عام.","الـ CTE (أي WITH name AS …) يسمّي نتيجة وسيطة، فيُقرأ التحليل الطويل من الأعلى إلى الأسفل ويمكن فحص كل خطوة وحدها.","الـ CTE التكراري فيه query ارتكاز، ثم UNION ALL، ثم query تكراري يرتبط بالـ CTE نفسه؛ ويتوقف حين لا يضيف أي تكرار صفوفًا جديدة.","مرّر عدّادًا للعمق (ومسارًا إن كان مفيدًا) عبر التكرار، وضع حدًّا للعمق حين يُحتمل أن تحتوي البيانات على حلقة."],"further":[{"title":"SQLite WITH clause and recursive common table expressions","url":"https://www.sqlite.org/lang_with.html"},{"title":"PostgreSQL WITH queries","url":"https://www.postgresql.org/docs/current/queries-with.html"}],"quiz":[{"q":"<p>أيّها scalar subquery مستخدم بشكل صحيح؟</p>","options":[{"text":"<code dir=\"ltr\">WHERE revenue &gt; (SELECT revenue FROM revenue_2025)</code>","why":"هذا الـ subquery يعيد صفًا لكل عميل. يستخدم SQLite الصف الأول بصمت؛ ويرمي PostgreSQL خطأً. وفي الحالتين ليس هذا هو المتوسط."},{"text":"<code dir=\"ltr\">FROM (SELECT AVG(revenue) FROM revenue_2025)</code> بلا اسم مستعار ولا ربط","why":"هذا جدول مشتق لا scalar subquery، ولا يرتبط وحده بالعملاء الذين تصفّيهم."},{"text":"<code dir=\"ltr\">WHERE customer_id = (SELECT customer_id FROM orders)</code>","why":"كالخيار الأول، يعيد الـ subquery صفوفًا كثيرة حيث يُتوقّع قيمة واحدة."},{"text":"<code dir=\"ltr\">WHERE revenue &gt; (SELECT AVG(revenue) FROM revenue_2025)</code>","why":"صحيح. دالة التجميع بلا GROUP BY تعيد صفًا واحدًا وعمودًا واحدًا بالضبط، فتحلّ محل قيمة واحدة."}],"answer":3},{"q":"<p>ما السبب الرئيسي الذي يدفع المحلّلين إلى إعادة بناء query متداخل في صورة CTEs؟</p>","options":[{"text":"تأخذ كل خطوة اسمًا ويُقرأ الـ query من الأعلى إلى الأسفل، ويمكنك تشغيل أي خطوة وحدها لفحصها.","why":"صحيح. المنطق نفسه؛ ما يتحسّن هو المقروئية وقابلية الفحص."},{"text":"الـ CTEs أسرع دائمًا من الـ subqueries.","why":"كثيرًا ما تدمج المحرّكات الـ CTEs وتخطّط لها كما تخطّط للـ subqueries، فيكون الأداء متشابهًا عادةً. اختر الـ CTEs من أجل الوضوح."},{"text":"الـ subqueries لا يمكن أن تحتوي على دوال تجميع، أما الـ CTEs فيمكن.","why":"يمكن للـ subqueries أن تجمّع؛ وإصلاح الـ fan-out في القسم السابق فعل ذلك بالضبط."}],"answer":0},{"q":"<p>يبدأ CTE تكراري من المديرة التنفيذية ويربط <code dir=\"ltr\">employees e ON e.manager_id = org.employee_id</code>. متى يتوقف؟</p>","options":[{"text":"بعد عدد ثابت من التكرارات تحدّده قاعدة البيانات.","why":"لا يوجد عدد مدمج للتكرارات؛ التكرار الجامح يستمر حتى تنفد الموارد."},{"text":"حين يصل إلى موظف قيمة <code dir=\"ltr\">manager_id</code> لديه NULL.","why":"المديرة التنفيذية هي صف الارتكاز، حيث يبدأ التتبّع. يسير التتبّع نزولًا وينتهي عند أشخاص لا يتبع لهم أحد."},{"text":"حين لا ينتج تكرارٌ أي صفوف جديدة، لأن المستوى الأخير لا يتبع له أحد.","why":"صحيح. كل تكرار لا يربط إلا الصفوف الناتجة عن التكرار السابق؛ وحين لا يتبع أحد لأي شخص في تلك المجموعة، ينتهي التكرار."},{"text":"حين يُبلغ حدّ عبارة LIMIT.","why":"لا يوجد LIMIT في جسم الـ CTE هنا. يمكن لـ LIMIT أن يحدّ التكرار، لكن التوقف الطبيعي هو تكرار فارغ."}],"answer":2},{"q":"<p>لماذا تضيف شرطًا مثل <code dir=\"ltr\">WHERE org.depth &lt; 20</code> إلى query تكراري على <code dir=\"ltr\">customers.referred_by</code>؟</p>","options":[{"text":"الـ CTEs التكرارية تتطلب عبارة WHERE لتعمل.","why":"لا تتطلّبها؛ query الموظفين في هذا الدرس بلا WHERE. إنه شبكة أمان، لا جزء من الصياغة."},{"text":"يجعل الـ query يستخدم index.","why":"حدود العمق لا تؤثّر في استخدام الـ index؛ إنها تحدّ عدد التكرارات فقط."},{"text":"يرتّب النتيجة حسب العمق.","why":"الترتيب يحتاج إلى ORDER BY في الـ SELECT النهائي. WHERE يصفّي فقط."},{"text":"إذا أنشأت بيانات سيئة حلقة إحالة يومًا ما (A أحال B، وB أحال A)، فلن ينتهي التكرار أبدًا بلا حدّ.","why":"صحيح. التسلسلات الهرمية التي يُدخلها أشخاص أو أنظمة قد تحتوي على حلقات، وحدّ العمق يحوّل الحلقة اللانهائية إلى query محدود."}],"answer":3}],"exercise":{"kind":"sql","starter":"-- Everyone below Mark Evans (employee 2), at any depth\nWITH RECURSIVE org AS (\n  SELECT employee_id, first_name, 1 AS depth\n  FROM employees\n  WHERE manager_id = 2\n)\nSELECT employee_id, first_name, depth\nFROM org\nORDER BY depth, employee_id;","solution":"WITH RECURSIVE org AS (\n  SELECT employee_id, first_name, 1 AS depth\n  FROM employees\n  WHERE manager_id = 2\n  UNION ALL\n  SELECT e.employee_id, e.first_name, org.depth + 1\n  FROM employees AS e\n  JOIN org ON e.manager_id = org.employee_id\n)\nSELECT employee_id, first_name, depth\nFROM org\nORDER BY depth, employee_id;","orderMatters":true,"title":"فريق مارك كاملًا","prompt":"<p>يحتاج مارك إيفانز (نائب الرئيس للعمليات، <code dir=\"ltr\">employee_id</code> = 2) إلى فريقه كاملًا لتخطيط عدد الموظفين: كل من يتبع له <strong>مباشرةً أو بشكل غير مباشر</strong>، دون مارك نفسه.</p>\n<p>أعِد <code dir=\"ltr\">employee_id</code> و<code dir=\"ltr\">first_name</code> و<code dir=\"ltr\">depth</code> (1 لمن يتبعون له مباشرةً، و2 لمن يتبعون لهؤلاء، وهكذا)، مرتّبة حسب <code dir=\"ltr\">depth</code> ثم <code dir=\"ltr\">employee_id</code>. الترتيب مهم.</p>\n<p>الارتكاز في الكود المبدئي صحيح بالفعل، لكنه يتوقف عند التابعين المباشرين. أضف الخطوة التكرارية.</p>\n","hints":["الـ CTE التكراري يحتاج إلى <code dir=\"ltr\">UNION ALL</code> يتبعه SELECT ثانٍ يرتبط بـ <code dir=\"ltr\">org</code>.","اربط <code dir=\"ltr\">employees AS e</code> بـ <code dir=\"ltr\">org</code> على <code dir=\"ltr\">e.manager_id = org.employee_id</code>: الأشخاص الذين مديرهم شخص وُجد بالفعل.","اختر <code dir=\"ltr\">e.employee_id, e.first_name, org.depth + 1</code> في الخطوة التكرارية حتى يكون كل مستوى أعمق بدرجة من أبيه."],"explanation":"<p>يجد الارتكاز التابعين المباشرين الثلاثة لمارك (سمير وجوليا وآدم) على العمق 1. ثم تضيف الخطوة التكرارية مرة بعد مرة الأشخاص الذين يقع مديرهم في التكرار السابق: أخصائيو الدعم الثلاثة تحت جوليا، وبن تحت سمير، على العمق 2. لا يجد التكرار التالي أحدًا يتبع لهؤلاء الأربعة، فيتوقف التكرار بسبعة أشخاص. بدء الارتكاز من <code dir=\"ltr\">manager_id = 2</code> بدل مارك نفسه هو ما يُبقيه خارج النتيجة.</p>\n","checkLabels":{}},"words":580,"readMinutes":3}