MySQL / الأسس العلائقية و SQL الدقيقة / الدرس 4
التجميع والأسئلة داخل الأسئلة
لخّص المجموعة الصحيحة وقارن المجموعات دون فقد معنى القيم المفقودة.
في هذه الصفحة
أهداف الدرس
- ميّز تصفية الصفوف من تصفية المجموعات.
- استخدم COUNT و SUM والاستعلامات المترابطة و ONLY_FULL_GROUP_BY بصورة صحيحة.
اختر المجتمع قبل التجميع
استخدم البيانات الأصلية. يختزل التجميع صفوفاً متعددة إلى نتيجة لكل مجموعة. تصفي WHERE الصفوف الداخلة وتشكل GROUP BY المجموعات وتصفي HAVING نتائجها. يجب أن يصفي تقرير الإيراد المدفوع الطلبات المدفوعة قبل الجمع. أما إضافة غير المدفوع ثم التحقق من وجود طلب مدفوع في المجموعة فيجيب عن سؤال مختلف ويضخم الإيراد.
عدّ الصفوف أو القيم المعروفة
تعد COUNT(*) الصفوف، وتعد COUNT(expression) قيم التعبير غير NULL. تتجاهل معظم دوال التجميع المدخلات NULL. تعيد SUM على مجموعة فارغة NULL لا صفراً، فاستخدم COALESCE عندما يعني الصفر فعلاً غياب الإيراد. وفي الربط الأيسر تعد COUNT(o.id) الطلبات المطابقة بينما تعد COUNT(*) صف العميل المحفوظ حتى دون طلب.
SELECT c.id, COUNT(o.id) AS order_count,
COALESCE(SUM(o.total),0) AS ordered_total
FROM customers c LEFT JOIN orders o ON o.customer_id=c.id
GROUP BY c.id ORDER BY c.id;
id | order_count | ordered_total
1 | 2 | 55.00
2 | 1 | 10.00
3 | 0 | 0.00
لدى Amina طلبان بإجمالي 55.00 و Leo طلب واحد بإجمالي 10.00 و Noor صفر بإجمالي 0.00. لا يسهم الصف الممدد بـ NULL في COUNT(o.id). واستبدالها بـ COUNT(*) يسجل طلباً زائفاً لـ Noor.
اجعل كل قيمة مختارة محددة
يفعّل MySQL 8.4 الوضع ONLY_FULL_GROUP_BY افتراضياً. يجب تجميع كل تعبير غير تجميعي مختار أو إثبات اعتماده الوظيفي على مفاتيح المجموعة. يعتمد اسم العميل على مفتاحه الأساسي، لكن حالة طلب عشوائي لا تعتمد على customer_id. إلغاء الوضع يخفي الغموض، و ANY_VALUE تعبّر عن عدم الاهتمام ولا تختار أحدث صف أو أكبره.
استخدم استعلاماً فرعياً للمقارنة
يوفر الاستعلام الفرعي القياسي عموداً واحداً وصفاً واحداً على الأكثر، ويعطي التجميع دون GROUP BY نتيجة واحدة حتى للمدخل الفارغ. تشير الاستعلامات المترابطة إلى الصف الخارجي بينما تحسب المستقلة مقارنة مشتركة. افهم شكل النتيجة قبل اختيار العامل؛ فالمساواة تحتاج قيمة قياسية و IN تقبل مجموعة و EXISTS تختبر الوجود.
SELECT id, total FROM orders
WHERE total > (SELECT AVG(total) FROM orders)
ORDER BY id;
id | total
101 | 25.00
102 | 30.00
تجمع الإجماليات الثلاثة إلى 65.00 ومتوسطها نحو 21.666667. يتجاوز الطلبان 101 و 102 المتوسط دون 103. تعتمد المنازل العشرية المعروضة للمتوسط على بيانات التعبير، لذا تعرض النتيجة أدناه الإجماليات الدقيقة المختارة فقط.
طابق الملخصات المستقلة
لتدقيق طلب اجمع order_items حسب order_id واحسب quantity * unit_price ثم قارنه بـ orders.total. لا تجمع إجماليات الطلبات بعد توسيعها إلى بنود. حدد معنى غياب البنود؛ يكشفها الربط الأيسر ويميز اختبار NULL غياب التفاصيل عن طلب ذي قيمة صفرية صحيحة. تعتمد صحة التقرير على هذه التعريفات بقدر اعتمادها على الصياغة.
الأخطاء الشائعة وإصلاحها
ERROR 1055 (42000) مع ONLY_FULL_GROUP_BY.
- لماذا يحدث؟
- اختارت مجموعة العميل حالة طلب رغم تعدد الحالات الممكنة.
- كيف تصلحه؟
- اجمع حسب الحالة المطلوبة أو استخدم تجميعاً يعبّر عن الحقيقة المقصودة.
- كيف تتجنب تكراره؟
- صف معنى كل عمود مخرج داخل المجموعة.
ERROR 1111 (HY000): Invalid use of group function.
- لماذا يحدث؟
- وضعت COUNT(*) داخل WHERE التي تصفي قبل التجميع.
- كيف تصلحه؟
- استخدم HAVING COUNT(*) >= 2 لشروط المجموعات.
- كيف تتجنب تكراره؟
- افصل شروط صفوف المدخل عن شروط نتائج التجميع.
ERROR 1242 (21000): Subquery returns more than 1 row.
- لماذا يحدث؟
- تلقت مقارنة قياسية إجماليات طلبات متعددة.
- كيف تصلحه؟
- اختر تجميعاً مبرراً أو عاملاً مجموعياً يوافق السؤال.
- كيف تتجنب تكراره؟
- توقع عدد أعمدة الاستعلام الفرعي وصفوفه أولاً.
اختبر فهمك
1. اعثر على العملاء ذوي طلبين على الأقل.
اعرض الحل المشروح
يعيد SELECT customer_id, COUNT(*) AS n FROM orders GROUP BY customer_id HAVING COUNT(*) >= 2 ORDER BY customer_id النتيجة 1/2. يتكون تجميعان للعملاء وتزيل HAVING مجموعة Leo ذات الطلب الواحد. ولا تدخل Noor لأن المصدر هو الطلبات.
2. احسب الإيراد المدفوع واشرح استبعاد طلب Amina الجديد.
اعرض الحل المشروح
تعطي SELECT SUM(total) FROM orders WHERE status = 'paid' القيمة 35.00 من 25.00 + 10.00. تستبعد التصفية الطلب 102 قبل التجميع. ويعطي جمع الجميع 65.00، أي قيمة الطلبات لا القيمة المدفوعة في هذا النموذج المبسط.
أهم ما تعلمته
- حدد المجتمع ومستوى الصف وسلوك المجموعة الفارغة.
- أبق ONLY_FULL_GROUP_BY مفعلاً وأصلح التفكير الغامض.