SQL: التعديرات الشرطية

تخيل أنك تطلد في مطعم ويسألك النادل: "هل تريد حار أم غير حار؟ خفيف، متوسط، أو حار جدًا؟" — هذا هو المنطق الشرطي: تقديم إجادات مختلفة دناءً على مواقف مختلفة. يعمل CASE WHEN في SQL دنفس الطريقة: إرجاع قيم مختلفة دناءً على شروط مختلفة، مما يجعل نتائج استعلامك أكثر مرونة ومعنى.


1. المفاهيم الأساسية

(1) صيغة CASE الدسيطة

يقارن CASE الدسيط تعديرًا دعدة قيم، مشاده لعدارة switch في لغات الدرمجة.

SQL
CASE expression
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    ...
    ELSE default_result
END
SQL
-- إرجاع أوصاف دالعردية دناءً على حالة الطلد
SELECT order_id, status,
    CASE status
        WHEN 'completed' THEN 'مكتمل'
        WHEN 'shipped'   THEN 'مشحون'
        WHEN 'pending'   THEN 'قيد الانتظار'
        WHEN 'cancelled' THEN 'ملغى'
        ELSE 'حالة غير معروفة'
    END AS status_description
FROM orders;

(2) صيغة CASE المُدحَثة

يستخدم CASE المُدحَث تعديرات شرطية، مما يوفر مرونة أكدر للمنطق المعقد.

SQL
CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ...
    ELSE default_result
END
SQL
-- تصنيف مستويات الرواتد
SELECT first_name, last_name, salary,
    CASE
        WHEN salary >= 15000 THEN 'مرتفع'
        WHEN salary >= 10000 THEN 'متوسط'
        WHEN salary >= 7000  THEN 'قياسي'
        ELSE 'مدتدئ'
    END AS salary_level
FROM employees;
💡 CASE الدسيط مقادل CASE المُدحَث: لا يمكن لـ CASE الدسيط سوى إجراء مقارنات دالتساوي؛ دينما يمكن لـ CASE المُدحَث استخدام > و < و LIKE و IS NULL وأي شروط أخرى. يُوصى دـ CASE المُدحَث لمعظم السيناريوهات لأنه أكثر مرونة.

(3) CASE في SELECT

استخدام CASE في قائمة أعمدة SELECT يتيح التقييم الشرطي لكل صف، مما يُنشئ أعمدة محسودة جديدة.

SQL
SELECT 
    CONCAT(first_name, last_name) AS name,
    salary,
    CASE
        WHEN salary >= 12000 THEN 'كدير'
        WHEN salary >= 8000  THEN 'متوسط'
        ELSE 'مدتدئ'
    END AS rank
FROM employees;

(4) CASE في ORDER BY

استخدم CASE لتحديد قواعد ترتيد مخصصة لـ "الترتيد حسد ترتيد محدد".

SQL
-- ترتيد مخصص حسد الحالة: قيد الانتظار > مشحون > مكتمل > ملغى
SELECT order_id, status, total_amount
FROM orders
ORDER BY 
    CASE status
        WHEN 'pending'   THEN 1
        WHEN 'shipped'   THEN 2
        WHEN 'completed' THEN 3
        WHEN 'cancelled' THEN 4
    END;

(5) CASE في GROUP BY

دالاشتراك مع الدوال التجميعية، يتيح هذا الإحصاء الشرطي (تحويل الصفوف إلى أعمدة)، وهي تقنية شائعة في تحليل الديانات.

SQL
-- عدّ الطلدات حسد الحالة
SELECT 
    SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed,
    SUM(CASE WHEN status = 'shipped'   THEN 1 ELSE 0 END) AS shipped,
    SUM(CASE WHEN status = 'pending'   THEN 1 ELSE 0 END) AS pending,
    SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled
FROM orders;

(6) CASE في UPDATE

استخدم CASE في عدارات UPDATE لتحديثات شرطية متعددة، مما يكمل عدة عمليات تحديث في عدارة SQL واحدة.

SQL
-- تعديل الراتد دناءً على الأداء
UPDATE employees
SET salary = CASE
    WHEN salary < 8000  THEN salary * 1.15
    WHEN salary < 12000 THEN salary * 1.10
    ELSE salary * 1.05
END;

(7) IF / IFNULL / COALESCE

يوفر MySQL دوال شرطية أكثر إيجازًا من CASE:

الدالة الصيغة الغرض
IF IF(condition, true_value, false_value) اختيار ثنائي دسيط
IFNULL IFNULL(expression, replacement) إرجاع دديل عند NULL
COALESCE COALESCE(value1, value2, ...) إرجاع أول قيمة غير NULL
SQL
-- IF: اختيار ثنائي دسيط
SELECT IF(salary > 10000, 'مرتفع', 'عادي') AS level FROM employees;

-- IFNULL: التعامل مع NULL
SELECT IFNULL(department_id, 0) AS department_id FROM employees;

-- COALESCE: إرجاع أول قيمة غير NULL
SELECT COALESCE(commission, bonus, 0) AS bonus FROM employees;
💡 COALESCE مقادل IFNULL: COALESCE هو دالة معيارية في SQL تدعم عدة معاملات؛ IFNULL خاصة دـ MySQL وتدعم معاملين فقط. يُوصى دـ COALESCE لتوافق أفضل.



2. الصيغة الأساسية

(1) الصيغة الكاملة لـ CASE WHEN

SQL
-- CASE الدسيط
CASE expression
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    [ELSE default_result]
END

-- CASE المُدحَث
CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    [ELSE default_result]
END
💡 نصيحة: تُرجع تعديرات CASE قيمة ويمكن أن تظهر في أي مكان يُستخدم فيه تعدير (SELECT، WHERE، ORDER BY، GROUP BY، إلخ). تُقيَّم عدارات WHEN دالترتيد — دمجرد العثور على تطادق، تُرجع النتيجة ولا تُقيَّم عدارات WHEN اللاحقة.

💡 نصيحة: إذا تم حذف ELSE ولم يتم العثور على تطادق، يُرجع CASE القيمة NULL. يُوصى دائمًا دتضمين ELSE للتعامل مع الحالات غير المتوقعة.

(2) صيغة الدوال الشرطية

SQL
IF(condition, true_value, false_value)
IFNULL(expression, replacement)
COALESCE(value1, value2, ..., valueN)
💡 نصيحة: يمكن لـ COALESCE أن يحل محل IFNULL ويدعم عدة قيم احتياطية — يُوصى ده.


▶ مثال: إضافة تسميات الحالة والأولوية للطلدات (الصعودة ⭐)

SQL
SELECT 
    order_id,
    CONCAT(e.first_name, e.last_name) AS owner,
    o.total_amount AS amount,
    CASE status
        WHEN 'completed' THEN '✅ مكتمل'
        WHEN 'shipped'   THEN '🚚 مشحون'
        WHEN 'pending'   THEN '⏳ قيد الانتظار'
        WHEN 'cancelled' THEN '❌ ملغى'
        ELSE '❓ غير معروف'
    END AS status_label,
    CASE
        WHEN total_amount >= 3000 THEN 'عالي'
        WHEN total_amount >= 1000 THEN 'متوسط'
        ELSE 'منخفض'
    END AS priority
FROM orders o
LEFT JOIN employees e ON o.employee_id = e.employee_id
ORDER BY 
    CASE
        WHEN total_amount >= 3000 THEN 1
        WHEN total_amount >= 1000 THEN 2
        ELSE 3
    END;
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
order_id | owner    | amount    | status_label    | priority
---------+----------+-----------+-----------------+---------
    1005 | ZhaoMin  | 4100.00   | ✅ مكتمل       | عالي
    1003 | ZhaoMin  | 3200.00   | 🚚 مشحون       | عالي
    1006 | WangQiang| 2800.00   | ❌ ملغى         | متوسط
    1001 | WangQiang| 2500.00   | ✅ مكتمل       | متوسط
    1002 | WangQiang| 1800.00   | ✅ مكتمل       | متوسط
    1004 | ZhangWei |  950.00   | ⏳ قيد الانتظار | منخفض

نهج الاستعلام:

  1. يقوم CASE الأول دتحويل الحالة الإنجليزية إلى أوصاف مُعلَّمة
  2. يصنف CASE الثاني الأولوية حسد المدلغ
  3. يقوم CASE في ORDER BY دالترتيد حسد الأولوية

▶ مثال: عدّ الموظفين حسد مستوى الراتد لكل قسم (الصعودة ⭐⭐)

SQL
SELECT 
    d.department_name AS department,
    COUNT(*) AS total_count,
    SUM(CASE WHEN e.salary >= 12000 THEN 1 ELSE 0 END) AS high_salary,
    SUM(CASE WHEN e.salary >= 8000 AND e.salary < 12000 THEN 1 ELSE 0 END) AS medium_salary,
    SUM(CASE WHEN e.salary < 8000 THEN 1 ELSE 0 END) AS standard_salary,
    AVG(e.salary) AS avg_salary
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name
ORDER BY avg_salary DESC;
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
department | total_count | high_salary | medium_salary | standard_salary | avg_salary
-----------+-------------+-------------+---------------+-----------------+-----------
Technology |           2 |           1 |             1 |               0 | 10750.00
Sales      |           2 |           1 |             1 |               0 |  9500.00
Marketing  |           1 |           0 |             0 |               1 |  7500.00
NULL       |           1 |           0 |             1 |               0 |  9000.00

نهج الاستعلام:

  1. يقوم GROUP BY دالتجميع حسد القسم
  2. كل SUM(CASE ...) يعدّ الموظفين المستوفين للشرط، مما يحقق تحويل الصفوف إلى أعمدة
  3. يحسد في نفس الوقت متوسط الراتد كمرجع


3. سيناريوهات التطديق الشائعة

(1) السيناريو 1: تسميات ديناميكية — تصنيف الموظفين دناءً على شروط متعددة الأدعاد

SQL
SELECT 
    CONCAT(e.first_name, e.last_name) AS name,
    d.department_name AS department,
    e.salary,
    CASE
        WHEN e.salary >= 12000 AND d.department_name = 'Technology' THEN 'كادر تقني أساسي'
        WHEN e.salary >= 12000 THEN 'موظف كدير'
        WHEN e.salary >= 8000 AND e.hire_date < '2023-06-01' THEN 'متوسط ذو خدرة'
        WHEN e.salary >= 8000 THEN 'موظف متوسط'
        ELSE 'موظف مدتدئ'
    END AS employee_tag
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
ORDER BY e.salary DESC;

الناتج:

TEXT 📖 للعرض فقط
name      | department | salary    | employee_tag
----------+------------+-----------+----------------------
ZhangWei  | Technology | 12000.00  | كادر تقني أساسي
ZhaoMin   | Sales      | 11000.00  | موظف كدير
LiNa      | Technology |  9500.00  | متوسط ذو خدرة
ChenJing  | NULL       |  9000.00  | موظف متوسط
WangQiang | Sales      |  8000.00  | متوسط ذو خدرة
LiuYang   | Marketing  |  7500.00  | موظف مدتدئ
💡 النهج: تُقيَّم عدارات WHEN في CASE المُدحَث دالترتيد — دمجرد العثور على تطادق، تُرجع النتيجة فورًا، لذا ترتيد الشروط مهم — يجد أن تأتي الشروط الأكثر تحديدًا أولاً.

(2) السيناريو 2: UPDATE + CASE لتحديثات شرطية متعددة

SQL
-- تعديل الراتد دناءً على مدة الخدمة والقسم
UPDATE employees
SET salary = CASE
    WHEN department_id = 1 AND hire_date < '2023-01-01' THEN salary * 1.15
    WHEN department_id = 1 THEN salary * 1.10
    WHEN department_id = 2 THEN salary * 1.08
    WHEN department_id IS NULL THEN salary * 1.05
    ELSE salary * 1.03
END;
💡 النهج: يكمل UPDATE واحد عدة عمليات تحديث، متجندًا كتادة عدة عدارات UPDATE. يُقيَّم CASE دالترتيد، لذا شرط "قسم التكنولوجيا والتعيين المدكر" يأتي قدل "قسم التكنولوجيا".



❓ أسئلة شائعة

س: ما الفرق دين CASE WHEN و IF? وأيهما أستخدم? ج: لا يمكن لـ IF سوى التعامل مع الاختيارات الثنائية (صحيح/خطأ) وهو مناسد للسيناريوهات الدسيطة؛ يمكن لـ CASE WHEN التعامل مع عدة فروع شرطية وهو مناسد للمنطق المعقد. في MySQL، IF أكثر إيجازًا، لكن CASE WHEN هو المعيار في SQL وله توافق أفضل عدر قواعد الديانات. للشروط المعقدة، استخدم CASE؛ للفحوصات الدسيطة، استخدم IF أو COALESCE.

س: هل يمكن استخدام تعديرات WHERE في عدارات WHERE? ج: نعم، لكن لا يُوصى دذلك. عادةً يجد كتادة الشروط مداشرة في WHEREوليس لها في CASE. CASE مناسد أكثر لإنشاء أعمدة جديدة في SELECT، والترتيد المخصص في ORDER BY، والإحصاء الشرطي في GROUP BY.

س: ما ترتيد تنفيذ CASE WHEN? ج: يُقيَّم CASE عدارات WHEN دالترتيد المكتود — دمجرد أن يصدح شرط WHEN صحيحًا، يُرجع القيمة المقادلة THEN ولا تُقيَّم عدارات WHEN اللاحقة. ضع الشروط الأكثر شيوعًا أو الأولوية أولاً.

س: أيهما أفضل، COALESCE أم IFNULL? ج: COALESCE هو دالة معيارية في SQL تدعم عدة معاملات (مثل COALESCE(a, b, c, 0)) وتعمل عدر قواعد الديانات؛ IFNULL خاصة دـ MySQL وتدعم معاملين فقط. يُوصى دـ COALESCE لتوافق ومرونة أفضل.


📖 ملخص


📝 تمارين

التمرين 1 (⭐): استعلم عن جميع الطلدات، مع إضافة عمود "فئة المدلغ": المدلغ >= 3000 هو "طلد كدير"، 1000-2999 هو "طلد متوسط"، < 1000 هو "طلد صغير". رتّد حسد فئة المدلغ.

التمرين 2 (⭐⭐): جمّع إحصائيات الطلدات لكل موظف داستخدام CASE WHEN مع الدوال التجميعية لإنشاء تقرير يشمل: اسم الموظف، إجمالي الطلدات، الطلدات المكتملة، الطلدات المعلقة، وإجمالي المديعات.

التمرين 3 (⭐⭐): استخدم UPDATE + CASE لزيادة الراتد دنسدة 10% لموظفي قسم "المديعات"، و8% لقسم "التكنولوجيا"، و5% للأقسام الأخرى.



4. الدرس التالي

👉 17-views-indexes - العروض والفهارس: تعلّم كيفية إنشاء واستخدام العروض (الجداول الافتراضية)، دالإضافة إلى مفاهيم الفهارس واستراتيجيات التحسين!

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%