التجميع GROUP BY

جملة GROUP BY في SQL هي واحدة من أقوى الأدوات لتحليل البيانات وتجميعها حسب فئات محددة. بدلاً من الحصول على إحصائية واحدة للجدول بأكمله، يمكنك تقسيم البيانات إلى مجموعات وحساب إحصائيات منفصلة لكل مجموعة. في هذا الدرس الشامل من سلسلة تعلم لغة SQL باللغة العربية، سنتعلم كيفية استخدام GROUP BY في SQL لتجميع البيانات، دمجها مع الدوال التجميعية في SQL، وإنشاء تقارير تحليلية احترافية لقواعد البيانات.

1. ما هو GROUP BY في SQL؟

GROUP BY هي جملة في لغة SQL تُستخدم لتجميع الصفوف التي لها نفس القيم في أعمدة محددة. عند استخدام GROUP BY في SQL، يتم تقسيم البيانات إلى مجموعات، ويمكنك تطبيق الدوال التجميعية (COUNT, SUM, AVG, MIN, MAX) على كل مجموعة بشكل منفصل.

البنية الأساسية لـ GROUP BY في SQL
صيغة GROUP BY
SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
ORDER BY column1;
قاعدة ذهبية: كل عمود في SELECT يجب أن يكون إما في GROUP BY أو داخل دالة تجميعية في SQL.
مثال توضيحي: الفرق بين بدون وبـ GROUP BY
جدول sales - مبيعات المنتجات
+----+----------+----------+--------+
| id | product  | quantity | price  |
+----+----------+----------+--------+
| 1  | لابتوب   | 2        | 3500   |
| 2  | ماوس     | 10       | 50     |
| 3  | لابتوب   | 1        | 3500   |
| 4  | شاشة     | 3        | 800    |
| 5  | ماوس     | 5        | 50     |
| 6  | لابتوب   | 3        | 3500   |
+----+----------+----------+--------+
بدون GROUP BY - إحصائية واحدة للكل
SELECT SUM(quantity) AS total_quantity
FROM sales;
النتيجة
+----------------+
| total_quantity |
+----------------+
| 24             |
+----------------+

-- مجموع كل المبيعات: 2+10+1+3+5+3 = 24
مع GROUP BY - إحصائية لكل منتج
SELECT 
    product,
    SUM(quantity) AS total_quantity
FROM sales
GROUP BY product;
النتيجة
+----------+----------------+
| product  | total_quantity |
+----------+----------------+
| لابتوب   | 6              | ← 2+1+3
| ماوس     | 15             | ← 10+5
| شاشة     | 3              |
+----------+----------------+

2. استخدام GROUP BY مع COUNT في SQL

أحد أكثر الاستخدامات شيوعاً لـ GROUP BY في SQL هو عد عدد العناصر في كل مجموعة باستخدام دالة COUNT.

مثال 1: عدد الموظفين في كل قسم
جدول employees
+----+----------+--------+------------+
| id | name     | salary | department |
+----+----------+--------+------------+
| 1  | أحمد     | 5000   | IT         |
| 2  | فاطمة    | 6000   | HR         |
| 3  | محمد     | 5500   | IT         |
| 4  | سارة     | 7000   | Sales      |
| 5  | علي      | 6500   | IT         |
| 6  | نورة     | 5800   | HR         |
| 7  | خالد     | 6200   | Sales      |
+----+----------+--------+------------+
تجميع الموظفين حسب القسم
SELECT 
    department AS القسم,
    COUNT(*) AS عدد_الموظفين
FROM employees
GROUP BY department
ORDER BY عدد_الموظفين DESC;
النتيجة
+------------+----------------+
| القسم      | عدد_الموظفين  |
+------------+----------------+
| IT         | 3              |
| HR         | 2              |
| Sales      | 2              |
+------------+----------------+
مثال 2: عدد الطلبات لكل عميل
استعلام SQL مع GROUP BY
SELECT 
    customer_name,
    COUNT(*) AS total_orders
FROM orders
GROUP BY customer_name
ORDER BY total_orders DESC;

3. استخدام GROUP BY مع SUM في SQL

يمكنك استخدام GROUP BY مع دالة SUM في SQL لحساب المجموع لكل مجموعة، مثل إجمالي المبيعات لكل منتج أو إجمالي الرواتب لكل قسم.

مثال 1: إجمالي الرواتب لكل قسم
تجميع الرواتب بـ GROUP BY
SELECT 
    department,
    SUM(salary) AS total_salaries,
    COUNT(*) AS employee_count
FROM employees
GROUP BY department;
النتيجة
+------------+----------------+----------------+
| department | total_salaries | employee_count |
+------------+----------------+----------------+
| IT         | 17000          | 3              | ← 5000+5500+6500
| HR         | 11800          | 2              | ← 6000+5800
| Sales      | 13200          | 2              | ← 7000+6200
+------------+----------------+----------------+
مثال 2: إجمالي الإيرادات لكل منتج
حساب الإيرادات بـ SQL GROUP BY
SELECT 
    product,
    SUM(quantity) AS total_sold,
    SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY product
ORDER BY total_revenue DESC;
النتيجة
+----------+------------+---------------+
| product  | total_sold | total_revenue |
+----------+------------+---------------+
| لابتوب   | 6          | 21000         | ← 6 × 3500
| شاشة     | 3          | 2400          | ← 3 × 800
| ماوس     | 15         | 750           | ← 15 × 50
+----------+------------+---------------+

4. استخدام GROUP BY مع AVG في SQL

دالة AVG مع GROUP BY في SQL تُستخدم لحساب المتوسط لكل مجموعة، مثل متوسط الراتب لكل قسم أو متوسط الدرجات لكل صف دراسي.

مثال 1: متوسط الراتب لكل قسم
تحليل الرواتب بـ GROUP BY
SELECT 
    department,
    COUNT(*) AS employees,
    AVG(salary) AS avg_salary,
    MIN(salary) AS min_salary,
    MAX(salary) AS max_salary
FROM employees
GROUP BY department
ORDER BY avg_salary DESC;
النتيجة
+------------+-----------+------------+------------+------------+
| department | employees | avg_salary | min_salary | max_salary |
+------------+-----------+------------+------------+------------+
| Sales      | 2         | 6600.00    | 6200       | 7000       |
| HR         | 2         | 5900.00    | 5800       | 6000       |
| IT         | 3         | 5666.67    | 5000       | 6500       |
+------------+-----------+------------+------------+------------+

5. GROUP BY مع أعمدة متعددة في SQL

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

مثال: المبيعات حسب المنتج والمدينة
جدول sales_detailed
+----+----------+----------+----------+--------+
| id | product  | city     | quantity | price  |
+----+----------+----------+----------+--------+
| 1  | لابتوب   | الرياض   | 2        | 3500   |
| 2  | لابتوب   | جدة      | 1        | 3500   |
| 3  | ماوس     | الرياض   | 10       | 50     |
| 4  | ماوس     | جدة      | 5        | 50     |
| 5  | لابتوب   | الرياض   | 3        | 3500   |
+----+----------+----------+----------+--------+
GROUP BY مع عمودين
SELECT 
    product,
    city,
    SUM(quantity) AS total_quantity,
    SUM(quantity * price) AS total_revenue
FROM sales_detailed
GROUP BY product, city
ORDER BY product, city;
النتيجة
+----------+----------+----------------+---------------+
| product  | city     | total_quantity | total_revenue |
+----------+----------+----------------+---------------+
| لابتوب   | الرياض   | 5              | 17500         |
| لابتوب   | جدة      | 1              | 3500          |
| ماوس     | الرياض   | 10             | 500           |
| ماوس     | جدة      | 5              | 250           |
+----------+----------+----------------+---------------+
ملاحظة: عند استخدام GROUP BY مع عدة أعمدة في SQL، يتم التجميع حسب كل تركيبة فريدة. مثلاً (لابتوب، الرياض) مجموعة منفصلة عن (لابتوب، جدة).

6. دمج GROUP BY مع WHERE في SQL

يمكنك استخدام WHERE قبل GROUP BY في SQL لتصفية البيانات أولاً، ثم تجميع النتائج المفلترة فقط.

ترتيب التنفيذ في SQL
ترتيب تنفيذ استعلام SQL
1. FROM    - اختيار الجدول
2. WHERE   - تصفية الصفوف
3. GROUP BY - تجميع البيانات
4. HAVING  - تصفية المجموعات (سنتعلمها في الدرس القادم)
5. SELECT  - اختيار الأعمدة
6. ORDER BY - ترتيب النتائج
7. LIMIT   - تحديد عدد النتائج
مثال 1: الموظفون براتب أعلى من 5500 لكل قسم
WHERE ثم GROUP BY
SELECT 
    department,
    COUNT(*) AS high_earners,
    AVG(salary) AS avg_high_salary
FROM employees
WHERE salary > 5500
GROUP BY department;
النتيجة
+------------+--------------+------------------+
| department | high_earners | avg_high_salary  |
+------------+--------------+------------------+
| IT         | 1            | 6500.00          | ← علي فقط
| HR         | 1            | 6000.00          | ← فاطمة فقط
| Sales      | 2            | 6600.00          | ← سارة وخالد
+------------+--------------+------------------+
مثال 2: مبيعات 2024 لكل منتج
تصفية بالتاريخ ثم تجميع
SELECT 
    product,
    COUNT(*) AS orders_count,
    SUM(quantity) AS total_sold
FROM sales
WHERE sale_date BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY product;

7. أمثلة عملية متقدمة لـ GROUP BY في SQL

مثال 1: تقرير المبيعات الشهري
تجميع حسب الشهر والسنة
SELECT 
    YEAR(order_date) AS year,
    MONTH(order_date) AS month,
    COUNT(*) AS total_orders,
    SUM(amount) AS total_sales,
    AVG(amount) AS avg_order_value
FROM orders
GROUP BY YEAR(order_date), MONTH(order_date)
ORDER BY year DESC, month DESC;
مثال 2: أفضل 5 عملاء
GROUP BY مع LIMIT
SELECT 
    customer_name,
    COUNT(*) AS total_orders,
    SUM(amount) AS total_spent,
    AVG(amount) AS avg_order
FROM orders
GROUP BY customer_name
ORDER BY total_spent DESC
LIMIT 5;
مثال 3: تحليل الأداء الأكاديمي
إحصائيات لكل صف دراسي
SELECT 
    class,
    COUNT(*) AS total_students,
    COUNT(score) AS students_attended,
    AVG(score) AS class_average,
    MIN(score) AS lowest_score,
    MAX(score) AS highest_score,
    COUNT(CASE WHEN score >= 50 THEN 1 END) AS passed,
    COUNT(CASE WHEN score < 50 THEN 1 END) AS failed
FROM exam_results
GROUP BY class
ORDER BY class_average DESC;
مثال 4: تحليل المخزون
تجميع حسب الفئة
SELECT 
    category,
    COUNT(*) AS product_count,
    SUM(stock) AS total_stock,
    AVG(price) AS avg_price,
    SUM(stock * price) AS inventory_value
FROM products
GROUP BY category
ORDER BY inventory_value DESC;
مثال 5: تقرير الموارد البشرية
تحليل شامل للموظفين
SELECT 
    department,
    COUNT(*) AS employees,
    SUM(salary) AS payroll,
    AVG(salary) AS avg_salary,
    MIN(salary) AS min_salary,
    MAX(salary) AS max_salary,
    MAX(salary) - MIN(salary) AS salary_range,
    AVG(YEAR(CURDATE()) - YEAR(hire_date)) AS avg_tenure
FROM employees
WHERE status = 'active'
GROUP BY department
ORDER BY payroll DESC;

8. الأخطاء الشائعة في GROUP BY

خطأ 1: عمود في SELECT ليس في GROUP BY
❌ خطأ شائع
-- ❌ خطأ: name ليس في GROUP BY ولا في دالة تجميعية
SELECT name, department, AVG(salary)
FROM employees
GROUP BY department;

-- ERROR: Column 'name' is not in GROUP BY clause
✅ الحل الصحيح
-- ✅ صحيح: فقط الأعمدة في GROUP BY أو الدوال التجميعية
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

-- أو إذا أردت الأسماء أيضاً:
SELECT name, department, salary
FROM employees
ORDER BY department;
خطأ 2: استخدام WHERE بدلاً من HAVING
❌ خطأ
-- ❌ خطأ: لا يمكن استخدام دالة تجميعية في WHERE
SELECT department, AVG(salary) AS avg_salary
FROM employees
WHERE AVG(salary) > 6000
GROUP BY department;

-- ERROR: Invalid use of aggregate function
✅ الحل: استخدم HAVING
-- ✅ صحيح: استخدم HAVING لتصفية المجموعات
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 6000;

-- سنتعلم HAVING بالتفصيل في الدرس القادم
خطأ 3: نسيان GROUP BY مع الدوال التجميعية
تذكر: إذا كان لديك عمود عادي ودالة تجميعية في SELECT، يجب استخدام GROUP BY على العمود العادي.

9. نصائح وأفضل الممارسات لـ GROUP BY في SQL

1. استخدم أسماء واضحة مع AS
تسمية واضحة
-- سيء
SELECT department, COUNT(*), AVG(salary)
FROM employees
GROUP BY department;

-- جيد
SELECT 
    department AS القسم,
    COUNT(*) AS عدد_الموظفين,
    AVG(salary) AS متوسط_الراتب
FROM employees
GROUP BY department;
2. رتب النتائج بـ ORDER BY

دائماً استخدم ORDER BY بعد GROUP BY في SQL لترتيب النتائج بشكل منطقي.

3. استخدم ROUND مع AVG
تقريب النتائج
SELECT 
    department,
    ROUND(AVG(salary), 2) AS avg_salary
FROM employees
GROUP BY department;
4. اجمع إحصائيات متعددة في استعلام واحد

بدلاً من تشغيل عدة استعلامات SQL منفصلة، اجمع كل الإحصائيات في استعلام GROUP BY واحد.

5. انتبه لترتيب الأعمدة في GROUP BY

عند استخدام GROUP BY مع عدة أعمدة في SQL، ترتيب الأعمدة لا يؤثر على النتيجة، لكن يُفضل ترتيبها منطقياً.

ملخص الدرس
  • GROUP BY في SQL: تُستخدم لتجميع الصفوف حسب قيم محددة
  • الدوال التجميعية: COUNT, SUM, AVG, MIN, MAX تعمل على كل مجموعة
  • القاعدة الذهبية: كل عمود في SELECT يجب أن يكون في GROUP BY أو دالة تجميعية
  • أعمدة متعددة: يمكن استخدام GROUP BY مع عدة أعمدة للتجميع التفصيلي
  • مع WHERE: WHERE تُصفي قبل التجميع، HAVING تُصفي بعد التجميع
  • ترتيب التنفيذ: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
  • Best Practice: استخدم أسماء واضحة، رتب النتائج، واجمع إحصائيات متعددة

الخطوة التالية: شرط HAVING

أكمل رحلتك التعليمية وانتقل إلى الدرس التالي لتعلم شرط HAVING وتطوير مهاراتك في قواعد البيانات.

الانتقال إلى الدرس التالي
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن