محتويات الدورة

MariaDB / الأساسي: الأسس العلاقية / الدرس 5

الربط والعد والتقارير المجمعة

أنشئ تقرير عملاء دون إسقاط المجموعات الخالية أو مضاعفة المجاميع، وافهم ما يمثله الصف في كل نتيجة وسيطة.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • توقع نتائج الربط الداخلي والخارجي.
  • فصل تصفية الصفوف عن تصفية المجاميع.

اسأل عما يمثله الصف الواحد

اكتب قبل الربط ما يمثله الصف: عميل أم حجز أم بند حجز. يكرر ربط واحد إلى كثير الأصل لكل فرع مطابق؛ يفيد ذلك في التفاصيل لكنه قد يضخم قيمة تخص الأصل عند جمعها. يحتفظ INNER JOIN بالمطابقات، ويحفظ LEFT JOIN أيضاً صفوف اليسار غير المطابقة مع أعمدة فرع NULL. لا يعرف أي ربط تلقائياً المستوى التجاري للمقياس.

عد مفتاح الفرع لا الصف المحفوظ

يحتوي المثال الكامل ببيانات مشتقة عميلين وحجزين للعميل 1. يحفظ LEFT JOIN العميل 2. تتجاهل COUNT(b.booking_id) مفتاح الفرع NULL فتعطي صفراً؛ أما COUNT(*) فتعد الصف الخارجي المحفوظ واحداً. أدرجنا عمودي العميل في GROUP BY لوضوح التجميع والتوافق مع ONLY_FULL_GROUP_BY. ينبغي توضيح قاعدة التقرير حتى لو قبل وضع SQL متساهل عبارة أقل دقة.

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
SELECT c.id, c.name, COUNT(b.booking_id) AS bookings
FROM (SELECT 1 AS id, 'Lina' AS name UNION ALL SELECT 2, 'Omar') AS c
LEFT JOIN (SELECT 11 AS booking_id, 1 AS customer_id
           UNION ALL SELECT 12, 1) AS b ON b.customer_id = c.id
GROUP BY c.id, c.name ORDER BY c.id;
الناتج المتوقع
id | name | bookings
1  | Lina | 2
2  | Omar | 0

يبقى العميل غير المطابق ظاهراً بعدد فروع صفر.

ضع شروط العلاقة الاختيارية في موضعها

لتقرير جميع العملاء وحجوزاتهم المدفوعة، ضع شرط الدفع في ON. نقله إلى WHERE يحذف غير المطابقين لأن NULL لا تساوي حالة الدفع، فيتغير التقرير. تصفي WHERE الصفوف قبل التجميع، وتصفي HAVING النتائج المجمعة مثل العملاء ذوي حجزين مطابقين فأكثر. راجع حالتي انعدام المطابقة والمطابقة الواحدة قبل اعتبار الاستعلام صحيحاً.

جمّع قبل ربط طرف متعدد آخر

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

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
SELECT booking_id, SUM(amount) AS paid
FROM (SELECT 10 AS booking_id, 20 AS amount
      UNION ALL SELECT 10, 30
      UNION ALL SELECT 20, 5) AS p
GROUP BY booking_id HAVING SUM(amount) > 40
ORDER BY booking_id;
الناتج المتوقع
booking_id | paid
10         | 50

تفحص HAVING المجاميع، بينما تجيب WHERE amount > 40 عن سؤال مختلف.

فسر التكرارات قبل إزالتها

تزيل DISTINCT الصفوف المتطابقة في الأعمدة المعروضة؛ لكنها لا تصلح علاقة ربط خاطئة أو SUM مضخماً. افحص المفاتيح والقيود أولاً. تعيد SUM دون صفوف NULL بينما تعيد COUNT صفراً، وقد يحتاج العرض قيمة افتراضية صريحة. استخدم ORDER BY مستقراً في التصدير ووثق إدراج الحجوزات الملغاة والمبالغ المعادة والعملاء الغائبين؛ فهذه دلالات لا يقررها المحسن عنك.

الأخطاء الشائعة وإصلاحها

تزداد المجاميع بعد إضافة الدفعات للتقرير

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

يُعد العميل بلا حجوزات كأنه يملك حجزاً

لماذا يحدث؟
عدت COUNT(*) الصف المحفوظ من LEFT JOIN.
كيف تصلحه؟
عد مفتاح فرع لا يقبل NULL بدلاً منه.
كيف تتجنب تكراره؟
ضمّن أصلاً غير مطابق في كل عينة ربط خارجي.

ERROR 1055: column is not in GROUP BY

لماذا يحدث؟
لا يملك عمود معروض غير مجمع قاعدة تجميع واضحة.
كيف تصلحه؟
اجمع الأبعاد المطلوبة أو طبق تجميعاً مبرراً.
كيف تتجنب تكراره؟
اعتمد أوضاع SQL مقصودة وتجنب اختيار قيم ممثلة اعتباطية.

اختبر فهمك

1. ليس للعميل 2 حجوزات مدفوعة. أين تضع شرط الدفع ليبقى بعدد صفر؟

اعرض الحل المشروح

ضعه في LEFT JOIN ... ON مع مساواة مفتاح العميل ثم عد مفتاح الحجز. سيحذف WHERE على حالة الفرع الصف الممتد بـ NULL. أبقِ نطاق العميل الإلزامي في WHERE لأنه يحدد العملاء المشمولين بالتقرير.

2. للحجز بندان بقيمتي 10 و15 ودفعات 5 و8 و12. ما الملخص الصحيح؟

اعرض الحل المشروح

مجموع البنود 25 ومجموع الدفعات 25. ينتج الربط المباشر ستة صفوف ومجموع بنود 75 ودفعات 50. اجمع البنود والدفعات كلّاً على حدة حسب booking_id ثم اربط الملخصين. لا تصلح DISTINCT على المبالغ لأن المبالغ المتساوية قد تكون صحيحة.

أهم ما تعلمته

  • تحدد تعددية الربط صلاحية المجموع.
  • تعبر WHERE وON وHAVING عن مراحل مختلفة للسؤال.

المراجع الرسمية