الوحدة 4 · SQL في العالم الحقيقي
المشروع الختامي: مراجعة أعمال الربع الرابع
17 دقراءة 4 دتمرين SQL
الدرس في لمحة
اجمع الدورة كلها في تحليل واحد، يقارن الربع الرابع من 2025 بالربع الرابع من 2024 حسب الدولة عبر خطوات CTE مسمّاة، ويطابق المجاميع، ويذكر التحفّظات، ويكتب إجابة تستطيع المديرة التنفيذية أن تتصرّف بناءً عليها.
- 1الخطوة 1: ثبّت التعريفات
- 2الخطوة 2: ابنِه في خطوات مسمّاة
- 3الخطوة 3: افحص قبل أن تصدّق
- 4الخطوة 4: اكتب الإجابة
- 5ما تستطيع فعله الآن
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
يأتي آخر طلب في السنة من رانيا نفسها: «سأعرض مراجعة الربع الرابع على مجلس الإدارة. كيف كان الربع الرابع من 2025 مقارنةً بالربع الرابع من 2024، دولةً دولة، وما القصة؟». هذه هي الدورة كلها في سؤال واحد. يحتاج إلى نطاقات تواريخ، وعمليات ربط بلا fan-out، وتجميع شرطي، وCTEs، وفحوص منطقية، وفي النهاية بضع جمل يستطيع مجلس الإدارة أن يتصرّف بناءً عليها. اعمل عليه كما تعمل على مكتب حقيقي: التعريفات أولًا، ثم الخطوات، ثم الفحوص، ثم الكلمات.
الخطوة 1: ثبّت التعريفات
قبل أي SQL، اكتب ما تعنيه كل كلمة في السؤال، وضعه حيث يستطيع الـ query أن يراه:
- الربع الرابع: من 1 أكتوبر إلى 31 ديسمبر، يُصفّى كنطاقات نصف مفتوحة، من اليوم الأول في الربع حتى 1 يناير دون أن يشمله، لعامي 2024 و2025 كليهما.
- الإيراد: مجموع
quantity * unit_price * (1 - discount)منorder_items، دون الشحن. - أي الطلبات: كل الحالات ما عدا ‘cancelled’، وهو التعريف المستخدم طوال هذه الدورة.
- الدولة: دولة العميل، من
customers. - مستوى تفصيل الإجابة: صف واحد لكل دولة.
توضع الفترات في CTE صغير خاص بها. كل خطوة لاحقة ترتبط به، فتغيير الربع يعني تعديل مكان واحد، لا ستة أماكن.
الخطوة 2: ابنِه في خطوات مسمّاة
WITH periods AS (
SELECT 'Q4 2024' AS period, '2024-10-01' AS start_date, '2025-01-01' AS end_date
UNION ALL
SELECT 'Q4 2025', '2025-10-01', '2026-01-01'
),
order_revenue AS (
-- grain: one row per order
SELECT order_id, SUM(quantity * unit_price * (1 - discount)) AS revenue
FROM order_items
GROUP BY order_id
),
q4_orders AS (
-- grain: one row per non-cancelled Q4 order
SELECT p.period, c.country, o.order_id, r.revenue
FROM orders AS o
JOIN periods AS p
ON o.order_date >= p.start_date AND o.order_date < p.end_date
JOIN customers AS c ON c.customer_id = o.customer_id
JOIN order_revenue AS r ON r.order_id = o.order_id
WHERE o.status <> 'cancelled'
),
by_country AS (
-- grain: one row per country
SELECT
country,
SUM(revenue) FILTER (WHERE period = 'Q4 2024') AS revenue_2024,
SUM(revenue) FILTER (WHERE period = 'Q4 2025') AS revenue_2025,
COUNT(*) FILTER (WHERE period = 'Q4 2025') AS orders_2025
FROM q4_orders
GROUP BY country
)
SELECT
country,
ROUND(revenue_2024, 2) AS revenue_q4_2024,
ROUND(revenue_2025, 2) AS revenue_q4_2025,
ROUND(100.0 * (revenue_2025 - revenue_2024) / NULLIF(revenue_2024, 0), 1) AS growth_pct,
ROUND(revenue_2025 / orders_2025, 2) AS avg_order_value_2025
FROM by_country
ORDER BY revenue_q4_2025 DESC;وراء كل تقنية هنا درس. الربط بـ periods يستخدم شرط نطاق في ON، فيوسم كل طلب بربعه ويُسقط كل ما عداه. ويضغط order_revenue العناصر أولًا، فيعدّ COUNT(*) لاحقًا الطلبات. ويضع FILTER السنتين جنبًا إلى جنب في مرور واحد. ويحمي NULLIF حساب النمو من دولة لم تبِع شيئًا في السنة الماضية.
الخطوة 3: افحص قبل أن تصدّق
فحصان يستغرقان دقيقة ويلتقطان معظم الأخطاء. أولًا، طابِق: يجب أن تجمع قيم revenue_q4_2025 الثماني إلى المجموع الناتج عن query أبسط على orders وorder_items وحدهما، أي 146,825.44، ويجب أن يجمع عمود 2024 إلى 52,537.10. وهي كذلك، بفارق لا يتجاوز سنتًا بسبب التقريب، فلا fan-out ولا صفوف ضائعة. ثانيًا، عُد إلى مجموعة فحوص جودة البيانات. المنتجات الموضوعة في الفئة الخطأ لا تهم على مستوى الدولة. أما الطلبان المرتجعان بلا سجلات إرجاع، والطلبات الـ 63 التي ما زالت ‘processing’ أو ‘shipped’، فتهم: بعض إيراد الربع الرابع من 2025 قد يُلغى أو يُسترد لاحقًا.
الخطوة 4: اكتب الإجابة
الـ query ليس هو المُخرَج؛ الإجابة هي المُخرَج. هذا ما يذهب إلى رانيا:
بلغ إيراد الربع الرابع من 2025 نحو 146.8 ألفًا، ارتفاعًا من 52.5 ألفًا في الربع الرابع من 2024 (+179%)، وتضاعف إيراد كل دولة على الأقل. النمو نمو في الحجم لا في حجم السلة: ارتفعت الطلبات من 228 إلى 642 بينما ثبت متوسط قيمة الطلب عند نحو 230. أصبحت المملكة المتحدة الآن أكبر أسواقنا (26.5 ألفًا، ارتفاعًا من 5.4 آلاف). أما نمو الأردن بنسبة +627% فمن أساس صغير. تحفّظ: في نهاية السنة كان 63 طلبًا من الربع الرابع، معظمها من ديسمبر، لا يزال قيد التجهيز أو الشحن، فقد تقتطع الإلغاءات والمرتجعات من الربع الرابع قليلًا.
من ثلاث إلى خمس جمل، والأرقام المهمة، وتحفّظ واحد صادق. لاحظ ما لا تقوله: لماذا نما الحجم. يقترح درس الـ cohorts أين تنظر بعد ذلك: كم من هذه الطلبات جاء من عملاء جدد اكتُسبوا في أسابيع Black Friday. والإجابة الجيدة تنتهي عادةً بالإشارة إلى السؤال الجيد التالي.
ما تستطيع فعله الآن
عُد بنظرك إلى طلب الدرس الأول عن الهوامش الضعيفة. انتقلت من SELECT وLIMIT إلى تحليل من خمس خطوات مسمّاة، بفحوص مدمجة وخلاصة مكتوبة. والأهم أنك بنيت عادات: اكتب السؤال ومستوى التفصيل قبل الـ query، واستخدم نطاقات التواريخ نصف المفتوحة، وضع شروط الجدول الأيمن في ON، وجمّع قبل الربط، واستخدم NOT EXISTS لـ«أبدًا»، وطابِق كل مجموع، وتعامل مع قيم NULL والفحوص الفاشلة كأسئلة. هذه العادات تنتقل إلى أي قاعدة بيانات، وأي لهجة، وأي نشاط تجاري. التمرين أدناه هو الأخير، وستكتبه من صفحة بيضاء.
أهم النقاط
- ابدأ أي تحليل حقيقي بتثبيت التعريفات (الفترات، والإيراد، والحالات) في مكان واحد، حتى تستخدمها كل الخطوات اللاحقة نفسها.
- ابنِ الـ query كخطوات CTE بمستويات تفصيل صريحة، وجمّع إلى صف واحد لكل طلب قبل ربط أي شيء يتكرّر.
- ضع فترات المقارنة جنبًا إلى جنب باستخدام FILTER، واحسب النمو باستخدام NULLIF حتى يعطي الأساس الصفري NULL بدل خطأ.
- طابِق الجدول النهائي مع مجموع مستقل، واذكر تحفّظات البيانات قبل أن تكتب الخلاصة.
- اعرض النتيجة بجمل بسيطة مع الأرقام التي تدعمها، بما في ذلك ما لا تستطيع البيانات أن تخبرك به بعد.