الترتيب والتصفية المتقدمة
نرتب النتائج، ونبحث بجزء من النص، ونتعامل مع الفراغ. ⏱ نحو 30 دقيقة.
- ترتب النتيجة بعمود أو أكثر تصاعديًّا وتنازليًّا.
- تحدد عدد الصفوف بـ
LIMITوOFFSET، وتحذف التكرار بـDISTINCT. - تصفّي بـ
INوBETWEENوLIKE. - تتعامل مع
NULLبـIS NULLوCOALESCE.
١الترتيب: ORDER BY
بلا ORDER BY لا يضمن النظام أي ترتيب للنتيجة. نرتب تصاعديًّا ASC (الافتراضي) أو تنازليًّا DESC:
SELECT name, priceFROM productsORDER BY price DESC;
| name | price |
|---|---|
| عسل سدر 500غ | 150 |
| مبخرة | 120 |
| تمر عجوة 1كغ | 90 |
| دلة قهوة | 75 |
| عسل زهور 500غ | 60 |
| زعفران 5غ | 55 |
| تمر سكري 1كغ | 45 |
| فناجين (6 قطع) | 40 |
| قهوة عربية 250غ | 35 |
| هيل 100غ | 28 |
| شاي أخضر | 18 |
| ماء زمزم 5لتر | 12 |
وبأكثر من عمود: يُرتَّب بالأول، وعند التساوي بالثاني:
SELECT name, category, priceFROM productsORDER BY category, price DESC;
| name | category | price |
|---|---|---|
| مبخرة | أدوات | 120 |
| دلة قهوة | أدوات | 75 |
| فناجين (6 قطع) | أدوات | 40 |
| زعفران 5غ | بهارات | 55 |
| هيل 100غ | بهارات | 28 |
| تمر عجوة 1كغ | تمور | 90 |
| تمر سكري 1كغ | تمور | 45 |
| عسل سدر 500غ | عسل | 150 |
| عسل زهور 500غ | عسل | 60 |
| قهوة عربية 250غ | مشروبات | 35 |
| شاي أخضر | مشروبات | 18 |
| ماء زمزم 5لتر | مشروبات | 12 |
ORDER BY تأتي في آخر الاستعلام، وتُنفَّذ بعد SELECT، فيمكن أن ترتب بالاسم المستعار.
٢أول N صفوف: LIMIT
-- أغلى 3 منتجاتSELECT name, priceFROM productsORDER BY price DESCLIMIT 3;
| name | price |
|---|---|
| عسل سدر 500غ | 150 |
| مبخرة | 120 |
| تمر عجوة 1كغ | 90 |
و OFFSET تتخطى صفوفًا، وهي أساس «الصفحات» في المواقع (الصفحة الثانية = تخطَّ 5، وخذ 5):
SELECT id, name FROM productsORDER BY idLIMIT 5 OFFSET 5;
| id | name |
|---|---|
| 6 | عسل زهور 500غ |
| 7 | دلة قهوة |
| 8 | فناجين (6 قطع) |
| 9 | هيل 100غ |
| 10 | زعفران 5غ |
٣حذف التكرار: DISTINCT
SELECT DISTINCT city FROM customers;| city |
|---|
| المدينة المنورة |
| الرياض |
| جدة |
| الدمام |
| تبوك |
| NULL |
كل مدينة مرة واحدة. ولاحظ أن NULL (لمى بلا مدينة) ظهرت قيمةً مستقلة.
٤قائمة ونطاق: IN و BETWEEN
IN تختصر سلسلة OR على العمود نفسه:
SELECT name, city FROM customersWHERE city IN ('جدة', 'الدمام', 'تبوك');
| name | city |
|---|---|
| ريم الشهري | جدة |
| سارة المطيري | الدمام |
| عبدالله الزهراني | جدة |
| ماجد الغامدي | تبوك |
و BETWEEN لنطاق يشمل الطرفين:
SELECT name, price FROM productsWHERE price BETWEEN 40 AND 75;
| name | price |
|---|---|
| تمر سكري 1كغ | 45 |
| عسل زهور 500غ | 60 |
| دلة قهوة | 75 |
| فناجين (6 قطع) | 40 |
| زعفران 5غ | 55 |
يشمل 40 و 75 نفسيهما. ويساوي: price >= 40 AND price <= 75.
SELECT id, order_date FROM ordersWHERE order_date BETWEEN '2025-04-01' AND '2025-04-30';
| id | order_date |
|---|---|
| 7 | 2025-04-01 |
| 8 | 2025-04-09 |
| 9 | 2025-04-20 |
٥البحث بجزء من النص: LIKE
LIKE تبحث بنمط فيه رمزان: % = أي عدد من الأحرف (حتى صفر)، و _ = حرف واحد بالضبط:
| النمط | يطابق |
|---|---|
'قهوة%' | يبدأ بـ «قهوة» |
'%عسل%' | فيه «عسل» في أي مكان |
'%غ' | ينتهي بـ «غ» |
'055_______1' | يبدأ بـ 055، ثم 7 أحرف، ثم 1 |
SELECT name FROM productsWHERE name LIKE '%قهوة%';
| name |
|---|
| قهوة عربية 250غ |
| دلة قهوة |
SELECT name, phone FROM customersWHERE name LIKE '%الحربي';
| name | phone |
|---|---|
| خالد الحربي | 0551000003 |
٦الفراغ: IS NULL
NULL «لا قيمة»، فلا تساوي شيئًا، ولا حتى NULL أخرى! لذلك = NULL لا تجد شيئًا أبدًا. نستخدم IS NULL و IS NOT NULL:
SELECT name FROM customers WHERE phone = NULL;| name |
|---|
| (لا توجد صفوف تحقق الشرط) |
SELECT name FROM customers WHERE phone IS NULL;| name |
|---|
| عبدالله الزهراني |
الأولى لا تعطي خطأ، بل نتيجة فارغة، وهذا أخطر لأنك قد لا تنتبه.
ولعرض قيمة بديلة مكان NULL: COALESCE (تعمل في كل الأنظمة)، أو IFNULL في MySQL و SQLite:
SELECT name, COALESCE(city, 'غير محددة') AS cityFROM customersWHERE id >= 8;
| name | city |
|---|---|
| هند السبيعي | المدينة المنورة |
| ماجد الغامدي | تبوك |
| لمى العنزي | غير محددة |
٧ترتيب أجزاء الاستعلام
الأجزاء تُكتب دائمًا بهذا الترتيب، وأي تبديل خطأ:
SELECT الأعمدةFROM الجدولWHERE الشرطORDER BY الترتيبLIMIT العدد;
توقّع وتحقّق
الترتيب التنازلي:
LIKE 'ع%' تطابق:
للبحث عن الفراغ:
NULL لا تساوي شيئًا.BETWEEN 10 AND 20 يشمل 20؟
الخلاصة
ORDER BYعمودASC/DESC، وتأتي قبلLIMITفي آخر الاستعلام.LIMIT n OFFSET mللصفحات، وDISTINCTلحذف التكرار.IN(قائمة)، وBETWEENأANDب يشمل الطرفين، وLIKEمع % و_.IS NULLلا =NULL، وCOALESCEلقيمة بديلة.
تحدٍّ برمجي: أغلى المنتجات المتوفرة
متوسطصفحة «الأكثر فخامة» في المتجر تعرض أغلى أربعة منتجات متوفرة في المخزون، ما عدا الأدوات.
- الأعمدة:
nameثمcategoryثمprice. - المنتجات المتوفرة فقط (المخزون أكبر من صفر)، وليست من تصنيف «أدوات».
- مرتبة من الأغلى، وأربعة فقط.
👀 اعرض النتيجة المطلوبة
| name | category | price |
|---|---|---|
| عسل سدر 500غ | عسل | 150 |
| تمر عجوة 1كغ | تمور | 90 |
| عسل زهور 500غ | عسل | 60 |
| زعفران 5غ | بهارات | 55 |
- الكود يعمل بلا أخطاء
- المنتجات الأربعة الصحيحة بالترتيب الصحيح
- تستخدم ORDER BY … DESC
- تستخدم LIMIT
💡 تلميح 1
💡 تلميح 2
category <> 'أدوات'حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
SELECT name, category, priceFROM productsWHERE stock > 0 AND category <> 'أدوات'ORDER BY price DESCLIMIT 4;