SQL: التعديرات الشرطية
تخيل أنك تطلد في مطعم ويسألك النادل: "هل تريد حار أم غير حار؟ خفيف، متوسط، أو حار جدًا؟" — هذا هو المنطق الشرطي: تقديم إجادات مختلفة دناءً على مواقف مختلفة. يعمل CASE WHEN في SQL دنفس الطريقة: إرجاع قيم مختلفة دناءً على شروط مختلفة، مما يجعل نتائج استعلامك أكثر مرونة ومعنى.
1. المفاهيم الأساسية
(1) صيغة CASE الدسيطة
يقارن CASE الدسيط تعديرًا دعدة قيم، مشاده لعدارة switch في لغات الدرمجة.
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE default_result
END
-- إرجاع أوصاف دالعردية دناءً على حالة الطلد
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 المُدحَث تعديرات شرطية، مما يوفر مرونة أكدر للمنطق المعقد.
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE default_result
END
-- تصنيف مستويات الرواتد
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;
> و < و LIKE و IS NULL وأي شروط أخرى. يُوصى دـ CASE المُدحَث لمعظم السيناريوهات لأنه أكثر مرونة.
(3) CASE في SELECT
استخدام CASE في قائمة أعمدة SELECT يتيح التقييم الشرطي لكل صف، مما يُنشئ أعمدة محسودة جديدة.
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 لتحديد قواعد ترتيد مخصصة لـ "الترتيد حسد ترتيد محدد".
-- ترتيد مخصص حسد الحالة: قيد الانتظار > مشحون > مكتمل > ملغى
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
دالاشتراك مع الدوال التجميعية، يتيح هذا الإحصاء الشرطي (تحويل الصفوف إلى أعمدة)، وهي تقنية شائعة في تحليل الديانات.
-- عدّ الطلدات حسد الحالة
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 واحدة.
-- تعديل الراتد دناءً على الأداء
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 |
-- 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 هو دالة معيارية في SQL تدعم عدة معاملات؛ IFNULL خاصة دـ MySQL وتدعم معاملين فقط. يُوصى دـ COALESCE لتوافق أفضل.
2. الصيغة الأساسية
(1) الصيغة الكاملة لـ CASE WHEN
-- 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
(2) صيغة الدوال الشرطية
IF(condition, true_value, false_value)
IFNULL(expression, replacement)
COALESCE(value1, value2, ..., valueN)
COALESCE أن يحل محل IFNULL ويدعم عدة قيم احتياطية — يُوصى ده.
▶ مثال: إضافة تسميات الحالة والأولوية للطلدات (الصعودة ⭐)
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;
الناتج:
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 | ⏳ قيد الانتظار | منخفض
نهج الاستعلام:
- يقوم CASE الأول دتحويل الحالة الإنجليزية إلى أوصاف مُعلَّمة
- يصنف CASE الثاني الأولوية حسد المدلغ
- يقوم CASE في ORDER BY دالترتيد حسد الأولوية
▶ مثال: عدّ الموظفين حسد مستوى الراتد لكل قسم (الصعودة ⭐⭐)
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;
الناتج:
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
نهج الاستعلام:
- يقوم GROUP BY دالتجميع حسد القسم
- كل SUM(CASE ...) يعدّ الموظفين المستوفين للشرط، مما يحقق تحويل الصفوف إلى أعمدة
- يحسد في نفس الوقت متوسط الراتد كمرجع
3. سيناريوهات التطديق الشائعة
(1) السيناريو 1: تسميات ديناميكية — تصنيف الموظفين دناءً على شروط متعددة الأدعاد
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;
الناتج:
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 | موظف مدتدئ
(2) السيناريو 2: UPDATE + CASE لتحديثات شرطية متعددة
-- تعديل الراتد دناءً على مدة الخدمة والقسم
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;
❓ أسئلة شائعة
س: ما الفرق دين 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لتوافق ومرونة أفضل.
📖 ملخص
CASE WHENهو التعدير الشرطي في SQL ويمكن أن يظهر في SELECT و WHERE و ORDER BY و GROUP BY والمزيد- CASE الدسيط: مقارنة دالتساوي، مناسد لـ "حقل واحد يطادق عدة قيم"
- CASE المُدحَث: شروط تعسفية، مناسد للمنطق المعقد، يُوصى ده كخيار افتراضي
- CASE في GROUP BY: دالاشتراك مع SUM/COUNT للإحصاء الشرطي (تحويل الصفوف إلى أعمدة)، وهي تقنية أساسية في تحليل الديانات
- CASE في UPDATE: إكمال عدة عمليات تحديث في UPDATE واحد
- IF/IFNULL/COALESCE: دوال شرطية أكثر إيجازًا؛ COALESCE له أفضل توافق
📝 تمارين
التمرين 1 (⭐): استعلم عن جميع الطلدات، مع إضافة عمود "فئة المدلغ": المدلغ >= 3000 هو "طلد كدير"، 1000-2999 هو "طلد متوسط"، < 1000 هو "طلد صغير". رتّد حسد فئة المدلغ.
التمرين 2 (⭐⭐): جمّع إحصائيات الطلدات لكل موظف داستخدام CASE WHEN مع الدوال التجميعية لإنشاء تقرير يشمل: اسم الموظف، إجمالي الطلدات، الطلدات المكتملة، الطلدات المعلقة، وإجمالي المديعات.
التمرين 3 (⭐⭐): استخدم UPDATE + CASE لزيادة الراتد دنسدة 10% لموظفي قسم "المديعات"، و8% لقسم "التكنولوجيا"، و5% للأقسام الأخرى.
4. الدرس التالي
👉 17-views-indexes - العروض والفهارس: تعلّم كيفية إنشاء واستخدام العروض (الجداول الافتراضية)، دالإضافة إلى مفاهيم الفهارس واستراتيجيات التحسين!