انتقل إلى محتوى الدرس
الدرس 31
دورة MySQL

تجميع الصفوف بجملة GROUP BY ودمج القيم عبر GROUP CONCATMySQL GROUP BY Clause and GROUP CONCAT

تعلّم تجميع الصفوف بجملة GROUP BY ودمج القيم عبر GROUP CONCAT بأسلوب MySQL 8 الحديث مع أمثلة استعلامات SQL وتطبيقات تفاعلية.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
8
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع
قسّم الصفوف المصفّاة إلى مجموعات مستقلة عبر GROUP BY واحسب الدوال التجميعية لكل مجموعة.

تقسم جملة GROUP BY الصفوف التي اجتازت شرط WHERE إلى مجموعات فرعية مستقلة بناءً على قيم عمود أو أكثر، وتُعيد صفاً ملخصاً واحداً لكل مجموعة فريدة.

  • التجميع لكل مجموعة: بدلاً من حساب COUNT(*) أو SUM() على الجدول كله، تُحسب كل دالة تجميعية داخل حدود مجموعتها فقط.
  • معاملة القيم الفارغة كمجموعة واحدة: يجمع محرك MySQL جميع الصفوف التي تحمل القيمة NULL في عمود التجميع داخل مجموعة واحدة مشتركة لعرض إحصائياتها معاً.

في MySQL 8 لم تعد جملة GROUP BY ترتّب النتائج تلقائياً؛ لذا أضف دائماً جملة ORDER BY صريحة عند الحاجة لترتيب المجموعات.

تقسيم الصفوف إلى مجموعات بـ GROUP BY ودمج القيم بدالة GROUP_CONCAT

مسار التنفيذ: FROM ثم تصفية الصفوف بـ WHERE ثم تقسيم المجموعات بـ GROUP BY ثم حساب الدوال في SELECT
مخطط توضيحي لدرس تجميع الصفوف بجملة GROUP BY ودمج القيم عبر GROUP CONCAT
مخطط توضيحي لدرس تجميع الصفوف بجملة GROUP BY ودمج القيم عبر GROUP CONCAT
SQL
-- Count orders and sum revenue per payment method
SELECT payment_method,
       COUNT(*)       AS orders_count,
       SUM(total_usd) AS method_revenue
FROM orders
WHERE order_status = 'paid'
GROUP BY payment_method
ORDER BY method_revenue DESC;
جمّع الصفوف باستخدام عدة أعمدة متتالية لاستخراج تقارير تفصيلية متعددة الأبعاد.

يتيح تمرير عدة أعمدة مفصولة بفواصل إلى جملة GROUP BY col1, col2 إنشاء مجموعة مستقلة لكل توليفة فريدة تجمع بين قيمتي العمودين معاً.

  • التحليل متعدد الأبعاد: يمكنك تجميع المبيعات حسب الدولة ثم المدينة GROUP BY country, city أو حسب القسم والمستوى الوظيفي لقراءة توزيع البيانات بدقة.
  • عدد الصفوف الناتجة: يساوي عدد صفوف النتيجة عدد التوليفات الفريدة الموجودة فعلياً في البيانات بعد التصفية.

احرص على إتباع التجميع المتعدد بجملة ORDER BY بنفس ترتيب الأعمدة لتظهر المجموعات الفرعية مرتبةً تحت فئاتها الرئيسية.

SQL
-- Breakdown headcount and average salary by dept and role
SELECT dept_id,
       job_role,
       COUNT(*)    AS staff_count,
       AVG(salary) AS avg_role_salary
FROM employees
WHERE is_active = 1
GROUP BY dept_id, job_role
ORDER BY dept_id ASC, job_role ASC;
اكتب استعلامات تجميعية قياسية تتوافق مع وضع ONLY_FULL_GROUP_BY المفعّل افتراضياً في MySQL 8.

يُفعّل محرك MySQL 8 الوضع القياسي الصارم ONLY_FULL_GROUP_BY افتراضياً لفرض قاعدة SQL القياسية الصارمة على جميع استعلامات التجميع:

  • القاعدة الذهبية للتجميع: كل عمود يُذكر في جملة SELECT يجب إما أن يكون مذكوراً صراحةً في جملة GROUP BY، أو موضوعاً داخل دالة تجميعية مثل MAX() أو COUNT().
  • سبب رفض الأعمدة العشوائية: إذا جمّعت الموظفين حسب رقم القسم GROUP BY dept_id وكتبت في العرض SELECT dept_id, full_name، فإن القسم الواحد يضم عشرات الأسماء المختلفة! لذا يرفض MySQL 8 الاستعلام بالخطأ 1055 بدلاً من عرض اسم موظف عشوائي مضلل.

إذا أردت استخراج جميع الأسماء داخل المجموعة استخدم GROUP_CONCAT(full_name)، أو استخدم MIN(full_name) أو ANY_VALUE(full_name) عند الرغبة بقيمة تمثيلية واحدة.

SQL
-- Valid under ONLY_FULL_GROUP_BY: grouped or aggregated
SELECT dept_id,
       COUNT(*)        AS headcount,
       MIN(hired_date) AS earliest_hire,
       MAX(salary)     AS top_salary
FROM employees
GROUP BY dept_id;
ادمج القيم المتعددة غير الفارغة داخل كل مجموعة في سلسلة نصية واحدة باستخدام دالة GROUP_CONCAT(col).

بينما تجمع SUM() الأرقام داخل المجموعة، يوفر MySQL الدالة التجميعية القوية GROUP_CONCAT(expr) لدمج النصوص أو القيم غير الفارغة في كل مجموعة داخل سلسلة نصية واحدة.

  • السلوك الافتراضي: تدمج GROUP_CONCAT(col) جميع القيم غير الفارغة في المجموعة وتفصل بينها بفاصلة عادية , افتراضياً.
  • منع تكرار القيم المدمجة: يمكنك إضافة الكلمة DISTINCT في بداية الدالة على الصورة GROUP_CONCAT(DISTINCT role_name) لدمج القيم الفريدة فقط دون تكرار.

إذا كانت جميع قيم العمود داخل المجموعة فارغة NULL، تُعيد الدالة القيمة NULL.

SQL
-- Combine unique product categories per supplier into one string
SELECT supplier_id,
       COUNT(*)                        AS total_products,
       GROUP_CONCAT(DISTINCT category) AS supplied_categories
FROM products
GROUP BY supplier_id;
تحكم في ترتيب العناصر المدمجة وشكل الفاصل النصي داخل GROUP_CONCAT(col) عبر ORDER BY و SEPARATOR.

تدعم دالة GROUP_CONCAT() جملتين داخليتين لضبط ترتيب العناصر قبل دمجها وتخصيص الفاصل النصي بينها:

  • الترتيب الداخلي ORDER BY: كتابة ORDER BY col ASC داخل قوسي الدالة يرتّب القيم الفرعية أبجدياً أو رقمياً قبل وصلها ببعضها.
  • الفاصل المخصص SEPARATOR: إضافة SEPARATOR ' | ' أو ', ' في نهاية الدالة يستبدل الفاصلة الافتراضية بأي نص تختاره.

احرص دائماً على الالتزام بالترتيب النحوي الصحيح داخل القوسين: DISTINCT أولاً، ثم اسم العمود، ثم ORDER BY، وأخيراً SEPARATOR.

SQL
-- Sort tags alphabetically with a clean custom separator
SELECT article_id,
       COUNT(*) AS tag_count,
       GROUP_CONCAT(
         DISTINCT tag_name
         ORDER BY tag_name ASC
         SEPARATOR ', '
       ) AS tag_list
FROM article_tags
GROUP BY article_id;
جدول مرجعي شامل يلخّص أنماط GROUP BY و GROUP_CONCAT وقواعد الوضع القياسي في MySQL 8.

يلخّص الجدول التالي الأنماط القياسية لجملة GROUP BY ودالة GROUP_CONCAT() في MySQL 8:

النمط / الميزةمثال الصياغةالقاعدة الأساسية في MySQL 8
تجميع بعمود واحدGROUP BY dept_idينتج صفاً واحداً لكل قيمة فريدة (وتجتمع قيم NULL في مجموعة واحدة)
تجميع متعدد الأعمدةGROUP BY dept_id, roleينتج صفاً واحداً لكل ثنائية فريدة من العمودين
الوضع القياسي الصارمONLY_FULL_GROUP_BYيجب أن يكون كل عمود في SELECT إما مجمّعاً أو داخل دالة تجميعية
دمج النصوص البسيطGROUP_CONCAT(name)يدمج القيم غير الفارغة بفاصلة , افتراضية
دمج مخصص كاملGROUP_CONCAT(DISTINCT x ORDER BY x SEPARATOR ', ')يزيل التكرار ويرتّب القيم ويفصل بينها بالفاصل المحدد

ملخص الدرس: أتقنت في هذا الدرس تقسيم الصفوف إلى مجموعات عبر GROUP BY، والتجميع الهرمي بعدة أعمدة، والالتزام بقاعدة ONLY_FULL_GROUP_BY القياسية، ودمج النصوص وترتيبها داخل كل مجموعة عبر GROUP_CONCAT().
الخطوة التالية والدرس القادم: سنتعلّم في الدرس القادم كيفية تصفية المجموعات بعد تجميعها باستخدام جملة HAVING والفرق الجوهري بينها وبين جملة WHERE.

SQL
-- Department summary with sorted employee list
SELECT dept_id,
       COUNT(*)    AS emp_count,
       SUM(salary) AS dept_payroll,
       GROUP_CONCAT(
         full_name ORDER BY full_name ASC SEPARATOR ', '
       ) AS members
FROM employees
WHERE is_active = 1
GROUP BY dept_id
ORDER BY dept_id ASC;
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

أتقنّا في هذا الدرس تجميع الصفوف بجملة GROUP BY ودمج القيم عبر GROUP CONCAT في MySQL 8 مع أمثلة عملية.

الخطوة التالية والدرس القادم

أكمل التدريبات والاختبار التفاعلي أدناه قبل الانتقال إلى الدرس التالي في مسار MySQL.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 GROUP BY Clause جملة تجميع الصفوف GROUP BY
جملة في SQL تقسم الصفوف إلى مجموعات بناءً على قيم عمود أو أكثر وتُعيد صفاً ملخصاً لكل مجموعة.
للمراجعة
02 ONLY_FULL_GROUP_BY وضع التجميع القياسي ONLY_FULL_GROUP_BY
الوضع القياسي الافتراضي في MySQL 8 الذي يشترط وجود كل عمود غير مجمّع في SELECT داخل جملة GROUP BY.
للمراجعة
03 GROUP_CONCAT() دالة دمج نصوص المجموعة GROUP_CONCAT()
دالة تجميعية في MySQL تدمج القيم غير الفارغة للمجموعة في نص واحد مع دعم إزالة التكرار والترتيب والفاصل المخصص.
للمراجعة
04 group_concat_max_len متغير الحد الأقصى للدمج group_concat_max_len
متغير النظام في MySQL الذي يحدد الطول الأقصى بالبايت للنص الناتج عن دالة GROUP_CONCAT().
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 SQL SQL
Structured Query Language
لغة الاستعلامات البنيوية القياسية
للمراجعة
02 ANSI ANSI
American National Standards Institute
المعهد القياسي المعتمد لقواعد التجميع الصارم ONLY_FULL_GROUP_BY
للمراجعة
03 CSV CSV
Comma-Separated Values
القيم المفصولة بفواصل التي تولّدها دالة GROUP_CONCAT افتراضياً
للمراجعة
04 LTS LTS
Long-Term Support
إصدار الدعم طويل الأمد مثل MySQL 8.4 LTS
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. اكتب استعلام SELECT على جدول products يعرض category و COUNT(*) باسم product_count و AVG(unit_price) باسم avg_price مجمّعةً حسب category.

  2. اكتب استعلام SELECT على جدول employee_skills يعرض emp_id ودالة GROUP_CONCAT(skill_name ORDER BY skill_name ASC SEPARATOR ', ') باسم skills مجمّعةً حسب emp_id.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

كيف تتعامل جملة GROUP BY مع الصفوف المتعددة التي يحمل عمود التجميع فيها القيمة الفارغة NULL؟

تتعامل جملة GROUP BY مع قيم NULL المتعددة كمجموعة واحدة مشتركة لعرض إحصائياتها في صف واحد.

02

لماذا يرفض MySQL 8 افتراضياً الاستعلام SELECT dept_id, full_name, COUNT(*) FROM employees GROUP BY dept_id؟

يمنع وضع ONLY_FULL_GROUP_BY اختيار عمود غير مجمّع مثل full_name لأن القسم الواحد يحتوي على عدة أسماء مختلفة.

03

ما الفاصل الافتراضي الذي تستخدمه دالة GROUP_CONCAT(col) عند عدم كتابة كلمة SEPARATOR؟

تستخدم دالة GROUP_CONCAT الفاصلة العادية ',' بدون مسافات كفاصل افتراضي بين القيم المدمجة.

04

ما الترتيب النحوي الصحيح للكلمات المفتاحية داخل قوسي الدالة GROUP_CONCAT()؟

يشترط بناء الجملة في MySQL كتابة DISTINCT أولاً، ثم التعبير، ثم ORDER BY، وأخيراً SEPARATOR.

05

ما اسم متغير النظام في MySQL الذي يتحكم في الحد الأقصى لطول النص الناتج عن GROUP_CONCAT()؟

يحدد المتغير group_concat_max_len (وقيمته الافتراضية 1024 بايت) أقصى طول للنص المدمج قبل اقتطاعه.

06

هل تضمن جملة GROUP BY في MySQL 8 ترتيب الصفوف الناتجة تصاعدياً تلقائياً دون كتابة ORDER BY؟

ألغى MySQL 8 الترتيب التلقائي مع GROUP BY لتمكين المحرك من استخدام التجميع السريع؛ لذا أضف ORDER BY دائماً عند الحاجة للفرز.

07

أين تُكتب جملة WHERE عندما يحتوي الاستعلام على كل من WHERE و GROUP BY؟

تُكتب جملة WHERE بعد FROM وقبل GROUP BY لأنها تصفّي الصفوف الفردية قبل تقسيمها إلى مجموعات.

08

كيف تتعامل الدالة GROUP_CONCAT(note) مع الصفوف التي تكون فيها قيمة العمود note فارغة NULL؟

تتجاهل GROUP_CONCAT القيم الفارغة كسائر الدوال التجميعية ولا تُعيد NULL إلا إذا خلت المجموعة تماماً من أي قيمة فعلية.