سلسلة sql للمحترفين تنفيذ تعليمات شرطية عبر CASE في SQL


محمد الميداوي

تستعرض هذه المقالة العبارة CASE، والتي تُستخدم لكتابة الشيفرات الشرطية (if-then).

استخدام CASE لحساب عدد الصفوف في العمود الذي يلبي شرطا معينًا

يمكن استخدام ‎CASE‎ مع SUM لحساب عدد العناصر المطابقة لشرط محدد (تشبه العبارة ‎COUNTIF‎ في Excel.)

الحيلة التي سنعتمدها هي أنّنا سنعيد نتائج ثنائية (binary) للدلالة على مطابقة الشرط، حيث يشير 1 إلى أنّ المدخل يطابق الشرط، فيما يشير 0 إلى عدم المطابقة، بعد ذلك سنجمع الوحدات التي حصلنا عليها للحصول على عدد المطابقات.

في الجدول ‎ItemSales‎ التالي، سنحاول عدّ العناصر الثمينة (EXPENSIVE):

Id ItemId Price PriceRating
1 100 34.5 EXPENSIVE
2 145 2.3 CHEAP
3 100 34.5 EXPENSIVE
4 100 34.5 EXPENSIVE
5 145 10 AFFORDABLE

سنستخدم الاستعلام التالي:

SELECT
 COUNT(Id) AS ItemsCount,
 SUM ( CASE
 WHEN PriceRating = 'Expensive' THEN 1
 ELSE 0
         END
       ) AS ExpensiveItemsCount
FROM ItemSales

سنحصل على الخرج التالي:

ItemsCount ExpensiveItemsCount
5 3

هذا استعلام آخر بديل:

SELECT
 COUNT(Id) as ItemsCount,
 SUM (
 CASE PriceRating
 WHEN 'Expensive' THEN 1
 ELSE 0
 END
 ) AS ExpensiveItemsCount
FROM ItemSales

البحث الشرطي

يمكن استخدام CASE مع العبارة SELECT لتصفية النتائج حسب شرط معيّن، بحيث لا تُعاد إلا النتائج التي تعيد القيمة المنطقية TRUE (هذا يختلف عن استخدام case العادي، والذي يتحقق من التكافؤ مع المُدخل وحسب).

SELECT Id, ItemId, Price,
     CASE WHEN Price < 10 THEN 'CHEAP'
 WHEN Price < 20 THEN 'AFFORDABLE'
 ELSE 'EXPENSIVE'
     END AS PriceRating
FROM ItemSales

سنحصل على الخرج التالي:

Id ItemId Price PriceRating
1 100 34.5 EXPENSIVE
2 145 2.3 CHEAP
3 100 34.5 EXPENSIVE
4 100 34.5 EXPENSIVE
5 145 10 AFFORDABLE

الشكل المُختزل لـ CASE

يقيّم الشكل المختزل لـ ‎CASE‎ تعبيرًا ما (عادةً ما يكون عمودًا)، ويقارنه بعدة قيم. هذا الشكل أقصر قليلاً من الشكل العادي، ويُعفيك من تكرار التعبير المقيَّم.

يمكن استخدام صياغة ‎ELSE‎ في الشكل على النحو التالي:

SELECT Id, ItemId, Price,
 CASE Price WHEN 5  THEN 'CHEAP'
 WHEN 15 THEN 'AFFORDABLE'
 ELSE 'EXPENSIVE'
 END as PriceRating
FROM ItemSales

من المهم أن تدرك أنه عند استخدام الشكل المختصر، فسيُقيَّم التعبير بالكامل في كل عبارة ‎WHEN‎. لذلك، فإنّ الشيفرة التالية:

SELECT
 CASE ABS(CHECKSUM(NEWID())) % 4
 WHEN 0 THEN 'Dr'
 WHEN 1 THEN 'Master'
 WHEN 2 THEN 'Mr'
 WHEN 3 THEN 'Mrs'
 END

قد تعيد القيمة المعدومة ‎NULL‎. لأنّه في كل عبارة ‎WHEN‎، تُستدعى ‎NEWID()‎ مع نتيجة جديدة. هذا يكافئ:

SELECT
 CASE
 WHEN ABS(CHECKSUM(NEWID())) % 4 = 0 THEN 'Dr'
 WHEN ABS(CHECKSUM(NEWID())) % 4 = 1 THEN 'Master'
 WHEN ABS(CHECKSUM(NEWID())) % 4 = 2 THEN 'Mr'
 WHEN ABS(CHECKSUM(NEWID())) % 4 = 3 THEN 'Mrs'
 END

لذلك يمكن أن تُفوِّت جميع عبارات ‎WHEN‎، لتُنتج القيمة ‎NULL‎.

استخدام CASE في عبارة ORDER BY

في الشيفرة، أدناه سنستخدم الأرقام 1،2،3 .. لتصنيف الطلب إلى أنواع:

SELECT * FROM DEPT
ORDER BY
CASE DEPARTMENT
 WHEN 'MARKETING' THEN  1
 WHEN 'SALES' THEN 2
 WHEN 'RESEARCH' THEN 3
 WHEN 'INNOVATION' THEN 4
 ELSE        5
 END,
          CITY

الخرج الناتج:

ID REGION CITY DEPARTMENT EMPLOYEES_NUMBER
12 New England Boston MARKETING 9
15 West San Francisco MARKETING 12
9 Midwest Chicago SALES 8
14 Mid-Atlantic New York SALES 12
5 West Los Angeles RESEARCH 11
10 Mid-Atlantic Philadelphia RESEARCH 13
4 Midwest Chicago INNOVATION 11
2 Midwest Detroit HUMAN RESOURCES 9

استخدام CASE في UPDATE

يزيد المثال التالي الأسعار في قاعدة البيانات:

UPDATE ItemPrice
SET Price = Price *
   CASE ItemId
 WHEN 1 THEN 1.05
 WHEN 2 THEN 1.10
 WHEN 3 THEN 1.15
 ELSE 1.00
    END

استخدام CASE مع القيم المعدومة NULL

في هذا المثال، يمثل الرقم "0" االقيم المعروفة، والتي توضوع في البداية، فيما يمثل "1" القيم NULL، و هي موضوعة في آخر الترتيب:

SELECT ID
 ,REGION
 ,CITY
 ,DEPARTMENT
 ,EMPLOYEES_NUMBER
   FROM DEPT
   ORDER BY
   CASE WHEN REGION IS NULL THEN 1
   ELSE 0
   END,
   REGION

سنحصل على الخرج التالي:

ID REGION CITY DEPARTMENT EMPLOYEES_NUMBER
10 Mid-Atlantic Philadelphia RESEARCH 13
14 Mid-Atlantic New York SALES 12
9 Midwest Chicago SALES 8
12 New England Boston MARKETING 9
5 West Los Angeles RESEARCH 11
15 NULL San Francisco MARKETING 12
4 NULL Chicago INNOVATION 11
2 NULL Detroit HUMAN RESOURCES 9

استخدام CASE في عبارة ORDER BY لترتيب السجلات حسب القيمة الدنيا لعمودين

لنفترض أنك بحاجة إلى ترتيب السجلات حسب القيمة الدنيا في عمودين. قد تستخدم بعض قواعد البيانات الدالتين غير التجميعيتين ‎MIN()‎ أو ‎LEAST()‎ (مثلا: ‎... ORDER BY MIN(Date1, Date2)‎)، ولكن في SQL القياسية، يجب استخدام التعبير ‎CASE‎.

يبحث التعبير ‎CASE‎ في الاستعلام أدناه في العمودين ‎Date1‎ و ‎Date2‎ ، ويبحث عن العمود الذي له أدنى قيمة، ثم يرتب السجلات وفقًا لتلك القيمة.

إليك الجدول التالي:

Id Date1 Date2
1 2017-01-01 2017-01-31
2 2017-01-31 2017-01-03
3 2017-01-31 2017-01-02
4 2017-01-06 2017-01-31
5 2017-01-31 2017-01-05
6 2017-01-04 2017-01-31

إليك الاستعلام التالي:

SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
       WHEN COALESCE(Date1, '1753-01-01') < COALESCE(Date2, '1753-01-01') THEN Date1
       ELSE Date2
   END

الخرج النتائج:

Id Date1 Date2
1 2017-01-01 2017-01-31
3 2017-01-31 2017-01-02
2 2017-01-31 2017-01-03
6 2017-01-04 2017-01-31
5 2017-01-31 2017-01-05
4 2017-01-06 2017-01-31

كما ترى ، الصف ذو المعّرف ‎Id = 1‎ جاء أولًا، وذلك لأنّ العمود ‎Date1‎ يحتوي أدنى سجل في الجدول، وهو ‎2017-01-01‎، الصف ذو المعرّف ‎Id‎ = ‎3‎ جاء ثانيًا، لأنّ العمود ‎Date2‎ يحتوي القيمة‎2017-01-02‎‎، وهي ثاني أقل قيمة في الجدول، وهكذا دواليك.

لقد رتّبنا السجلات من ‎2017-01-01‎ إلى ‎2017-01-06‎ تصاعديًا، بغض النظر عن العمود ‎Date1‎ أو ‎Date2‎ الذي جاءت منه تلك القيم.

ترجمة -وبتصرّف- للفصول 7 و 8 و 9 من الكتاب SQL Notes for Professionals





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن