قراءة البيانات من الجداول باستخدام SELECT
السلام عليكم ورحمة الله وبركاته
المقدمة
الآن حان الوقت لنتعلم أهم وأكثر الأوامر استخدامًا في الـ SQL وهو أمر الـ SELECT
وهو كأمر بسيط لكن قوي جدًا في نفس الوقت
هذا الأمر هو ما ستستخدمه 90% من الوقت في تعاملك مع قواعد البيانات
لأن معظم العمليات التي ستقوم بها ستكون قراءة البيانات من الجداول
ووظيفتك تكون كيف تكتب Query
سريعة وتؤدي الغرض المطلوب منها
لأنك قد تكتب Query
تقوم بقراءة بيانات من جدول كبير جدًا، وقد تستغرق وقتًا طويلًا
ثم يأتي شخص آخر يحقق لك نفس المطلوب لكن بـ Query
أفضل وأسرع
لذلك من المهم جدًا أن تتعلم كيف تكتب Query
فعالة وسريعة باستخدام أمر الـ SELECT
في هذه المقالة سنتعلم كل شيء عن أمر الـ SELECT
من الأساسيات البسيطة إلى الاستخدامات المتقدمة
ما هو أمر الـ SELECT ؟
أمر الـ SELECT
يستخدم لـ قراءة واسترجاع البيانات من الجداول في قاعدة البيانات
وكلمة Query
تعني استعلام أو يمكنك أن تتخيل أن الـ Query
في الأساس طريقة لـ طرح سؤال على قاعدة البيانات، وستقوم قاعدة البيانات بالإجابة عليك بالنتيجة المطلوبة
لذالك كلما سألت السؤال بطريقة صحيحة، كلما كانت الإجابة دقيقة وسريعة
بالتالي بافتراض أننا لدينا بيانات كثيرة من الطلاب في جدول الـ Students
ثم قلت لك أحضر لي أسماء جميع الطلاب
فستقوم بكتابة أمر الـ SELECT
كالتالي:
SELECT name FROM Students;
هذا الأمر يعني "أريد قراءة عمود الاسم من جدول الطلاب" هكذا بكل بساطة
لنسأل سؤال آخر، لنفترض أنك تريد قراءة تريد أسماء وأعمار جميع الطلاب الذين أعمارهم أكبر من 20
سنة
فستكتب الأمر كالتالي:
SELECT name, age FROM Students WHERE age > 20;
حتى أنك حين تقرأ الـ Query
هذه، ستشعر وكأنك تتحدث مع قاعدة البيانات بلغة بشرية بسيطة
SELECT name, age
تعني "أريد قراءة عمود الاسم وعمود العمر"FROM Students
تعني "من جدول الطلاب"WHERE age > 20
تعني "حيث العمر أكبر من20
"
هذا هو جوهر أمر الـ SELECT
، وهو ما ستستخدمه في معظم تعاملاتك مع قواعد البيانات
ملحوظة
: تذكر أن أوامر الـSQL
يمكننا كتابتهاlowercase
أوUPPERCASE
أو حتىcamelCase
لكن المتعارف عليه هو كتابة الأوامر بـUPPERCASE
للتفريق بينها وبين أسماء الجداول والأعمدة التي عادة ما تكون بـlowercase
أوcamelCase
بالتالي في الـQuery
يمكنك استنتاج بمجرد النظر أنSELECT
وFROM
وWHERE
هي أوامرSQL
بينماname
وage
وStudents
هي أسماء أعمدة أو جداول
لذا يفضل كتابة الأوامر بـUPPERCASE
لتسهيل القراءة والفهم
تجهيز الجدول للأمثلة العملية
قبل أن نبدأ في تعلم أمر الـ SELECT
والتطبيق عليه، دعونا نتفق على جدول موحد سنستخدمه في جميع الأمثلة
وهو نفس جدول الـ Students
الذي استخدمناه في المقالات السابقة
CREATE TABLE Students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
age INT,
level VARCHAR(50) DEFAULT 'Beginner'
);
ولنفترض أن لدينا البيانات التالية في جدول الـ Students
:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
بالطبع لن اعيد شرح كيف نضيف البيانات إلى الجدول بإستخدام الـ INSERT
، لأننا فعلنا ذلك في المقالات السابقة
الآن دعونا نبدأ في تعلم كيفية استخدام أمر الـ SELECT
لقراءة هذه البيانات بطرق مختلفة
قراءة جميع البيانات من الجدول
أبسط استخدام لأمر الـ SELECT
هو قراءة جميع البيانات من أي جدول:
SELECT * FROM Students;
هنا الرمز *
يعني "جميع الأعمدة"
بالتالي هذا الأمر ببساطة يعني "أريد كل البيانات من جدول الطلاب"
وستكون النتيجة كالتالي:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
النتيجة ستكون جميع البيانات الموجودة في جدول الـ Students
كما هو موضح في الجدول أعلاه
قراءة أعمدة محددة فقط
في حالة أنك تريد عرض بيانات من أعمدة محددة، يمكنك تحديد الأعمدة التي تحتاجها فقط
مثل name
و age
فقط، بدلاً من قراءة جميع الأعمدة
فستطيع تحديد الأعمدة التي تريدها بدلاً من استخدام *
مثلاً إذا كنت تريد أسماء الطلاب وأعمارهم فقط:
SELECT name, age FROM Students;
والنتيجة ستكون:
+-----------------+-----+
| name | age |
+-----------------+-----+
| Ahmed Moustafa | 20 |
| Osama Ali | 19 |
| Mohamed Adel | 22 |
| Kamal Mahmoud | 21 |
| Ayman Hassan | 20 |
+-----------------+-----+
لاحظ أننا حددنا فقط الأعمدة name
و age
بالتالي تم عرض أسماء الطلاب وأعمارهم فقط
وإذا كنت تريد عمود واحد فقط، مثل أسماء الطلاب:
SELECT name FROM Students;
النتيجة:
+-----------------+
| name |
+-----------------+
| Ahmed Moustafa |
| Osama Ali |
| Mohamed Adel |
| Kamal Mahmoud |
| Ayman Hassan |
+-----------------+
ملحوظة
: يفضل تحديد الأعمدة التي تحتاجها فقط بدلاً من استخدام*
لأن هذا يحسن الأداء ويقلل من حجم البيانات التي يتم سحبها ونقلها من قاعدة البيانات إلى التطبيق
وأيضًا يجعل النتائج أكثر وضوحًا وتعرف ماذا تحتاج بالضبط
تصفية البيانات باستخدام WHERE
حسنًا في الحياة العملية ستجد أنك تملك جداول بها مئات أو آلاف البيانات
فمثلاً جدول الطلاب قد يحتوي على مئات الطلاب، فهل كل مرة تحتاج لعمل Query
لقراءة جميع البيانات ؟
الإجابة بالطبع لا، بل نحن نحتاج لبيانات محددة تحقق شروط معينة
أحيانًا نطلب أعطني جميع الطلاب الذين أعمارهم أكبر من 20
سنة
أول أعطني أعلى 10
طلاب
بمعنى أخر تريد عرض البيانات التي تحقق شروط معينة فقط
هنا يأتي دور WHERE
الذي يُستخدم لكي يصفي البيانات حسب الشروط التي نحددها
شكل كتابة الأمر بسيطة جدًا فقط تضيف WHERE
بعد FROM
وتحدد الشروط التي تريدها
SELECT * FROM Students WHERE age > 20;
هنا قلنا له "أريد قراءة جميع البيانات من جدول الطلاب الذي أعمارهم أكبر من 20
"
النتيجة ستكون:
+----+---------------+-----+-----------+------------------------+
| id | name | age | level | email |
+----+---------------+-----+-----------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
+----+---------------+-----+-----------+------------------------+
بالطبع الناتج يحتوي على الطلاب الذين أعمارهم أكبر من 20
فقط
وهما شخصين في جدول الـ Students
الخاص بنا وهما Mohamed Adel
و Kamal Mahmoud
بالتالي يمكننا استخدام شرط WHERE
لتصفية النتائج حسب ما نريد
فمثلا إذا أردنا جميع الطلاب الذين مستواهم Advanced
:
SELECT * FROM Students WHERE level = 'Advanced';
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
كما ترى أمر الـ SELECT
مع شرط WHERE
يسمح لنا بتصفية البيانات حسب الشروط التي نحددها بكل بساطة كأنك تتحدث مع قاعدة البيانات
ربط شروط متعددة باستخدام AND و OR
ما رأيك بإحضار الطلاب الذين مستواهم Advanced
و أكبر من 20
سنة ؟
هكذا لدينا شريطين وهما مستوى الطالب و عمر الطالب
يمكنك دمج الشرطين معًا باستخدام AND
أو OR
حسب ما تريد
هنا بما أننا نريد الطلاب الذين مستواهم Advanced
و أعمارهم أكبر من 20
فسنستخدم AND
لربط الشرطين معًا:
SELECT * FROM Students WHERE level = 'Advanced' AND age > 20;
لاحظ أننا استخدمنا AND
لربط شرطين معًا
مثل اللغة الإنجليزية، يمكننا استخدام AND
لربط أكثر من شرط معًا وبالتالي يجب أن تتحقق جميع الشروط لكي تكون النتيجة صحيحة
أو نستحدم OR
لربط أكثر من شرط بحيث يكفي أن يتحقق شرط واحد فقط
وهذه الشروط مرتبطة بنوع من البيانات قد تعرفه أو درسته في عالم البرمجة وهو الـ Boolean
وهو تمامًا ما نستخدمه في الـ SQL
في الـ WHERE
والـ Boolean
هو نوع من البيانات مثل Integer
أو String
يمكن أن يكون له قيمتين فقط true
أو false
عندما نستخدم AND
، يجب أن تكون جميع الشروط صحيحة true
لكي يتحقق الشرط
وعندما نستخدم OR
، يكفي أن يكون أحد الشروط صحيحًا true
لكي تتحقق النتيجة
على أي حال نتيجة الـ Query
التى كتبناها سابقًا ستكون:
+----+-----------------+-----+-----------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+-----------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
+----+-----------------+-----+-----------+------------------------+
هنا لدينا طالب واحد فقط وهو Mohamed Adel
وهو الذي حقق الشرطين level = 'Advanced'
و age > 20
إذا أردنا الطلاب الذين مستواهم Advanced
أو أعمارهم أكبر من 20
، يمكننا استخدام OR
:
SELECT * FROM Students WHERE level = 'Advanced' OR age > 20;
النتيجة ستكون:
+----+-----------------+-----+-----------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+-----------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+-----------+------------------------+
وبالطبع يمكنك دمج الشروط باستخدام AND
و OR
بالعدد الذي تريده
أهمية استخدام الأقواس
الأقواس ()
في الـ SQL
مهمة جدًا لتحديد أولوية تنفيذ الشروط، تمامًا مثل الرياضيات
دعنا نرى مثالاً عملياً:
المثال الأول: مع استخدام الأقواس
SELECT * FROM Students
WHERE (level = 'Advanced' OR level = 'Beginner')
AND age > 20;
هنا نقول: "أريد الطلاب الذين (مستواهم Advanced
أو Beginner
) وفي نفس الوقت عمرهم أكبر من 20
"
بسبب الأقواس، سيتم تنفيذ الشرط بهذا الترتيب:
- أولًا:
(level = 'Advanced' OR level = 'Beginner')
- نجد الطلاب المتقدمين أو المبتدئين - ثانيًا:
AND age > 20
- نأخذ الطلاب الذي عمرهم أكبر من20
وهنا بسبب وجود AND
فسيجب أن يتحقق الشرطين معًا، الشرط الذي على يسار الـ AND
والشرط الذي على يمينه
النتيجة:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
+----+-----------------+-----+--------------+------------------------+
المثال الثاني: بدون استخدام الأقواس
SELECT * FROM Students
WHERE level = 'Advanced' OR level = 'Beginner' AND age > 20;
هنا بدون أقواس، الـ SQL
يطبق قاعدة الأولوية في التنفيذ بالتالي الـ AND
له أولوية أعلى من الـ OR
كأنك كتبت الشرط هكذا:
SELECT * FROM Students
WHERE level = 'Advanced' OR (level = 'Beginner' AND age > 20);
لذلك سيتم تنفيذ الشرط كالتالي:
- أولًا:
level = 'Advanced'
- نجد الطلاب المتقدمين - ثانيًا:
(level = 'Beginner' AND age > 20)
- نجد الطلاب المبتدئين الذين عمرهم أكبر من20
وهنا بسبب وجود OR
بين الشرطين، يكفي أن يتحقق أحد الشرطين لكي تظهر النتيجة
النتيجة ستكون كالتالي:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
لاحظ الفرق:
- في المثال الأول بالشرط
(level = 'Advanced' OR level = 'Beginner') AND age > 20
ظهر طالبين فقط وهمMohamed Adel
مستواهAdvanced
وعمره أكبر من20
Kamal Mahmoud
مستواهBeginner
وعمره أكبر من20
- هنا نحن نطبق الشرطين معًا بسبب وجود
AND
- في المثال الثاني بالشرط
level = 'Advanced' OR (level = 'Beginner' AND age > 20)
ظهر ثلاثة طلاب وهمMohamed Adel
مستواهAdvanced
Kamal Mahmoud
مستواهBeginner
وعمره أكبر من20
Ayman Hassan
مستواهAdvanced
- هنا يكفي أن نطبق أحد الشرطين بسبب وجود
OR
عوامل المقارنة المختلفة في WHERE
في الـ SQL
، نستخدم عوامل المقارنة مثل =
و >
و <
وغيرها لتحديد الشروط التي نريدها في جملة WHERE
لدينا أنواع كثيرة منها الأساسية التي سنتناولها في هذا القسم
ثم لدينا أنواع مميزة أو متقدمة مثل LIKE
و IN
و BETWEEN
وغيرها
العوامل الأساسية
=
: يساوي!=
أو<>
: لا يساوي>
: أكبر من<
: أصغر من>=
: أكبر من أو يساوي<=
: أصغر من أو يساوي
لا أظن أن عليا شرح هذه العوامل لأنها واضحة جدًا لذا لا داعي للاستفاضة فيها، لكن دعنا نرى بعض الأمثلة العملية على استخدامها بشكل سريع
-- الطلاب الذين مستواهم متقدم
SELECT name, level FROM Students WHERE level = 'Advanced';
-- الطلاب الذين ليسوا مبتدئين
SELECT name, level FROM Students WHERE level != 'Beginner';
-- الطلاب الذين عمرهم أكبر من 20
SELECT name, age FROM Students WHERE age > 20;
-- الطلاب الذين عمرهم أقل من أو يساوي 20
SELECT name, age FROM Students WHERE age <= 20;
ملحوظة
: في بعض أنظمة الـDBMS
، يمكنك استخدام<>
بدلاً من!=
أو العكس أو كليهما بحسب الـDBMS
الذي تستخدمه
البحث عن جملة باستخدام LIKE
أحيانًا نحتاج للبحث عن البيانات التي تحتوي على جزء معين من النص وليس النص بالكامل
مثلاً، إذا كنت تريد البحث عن جميع الطلاب الذين أسماؤهم تبدأ بحرف معين أو تحتوي على كلمة معينة
هنا يأتي دور LIKE
الذي يُستخدم للبحث في النصوص باستخدام مثل هذه الشروط
رموز البحث المستخدمة مع LIKE
عندما نستخدم LIKE
، لدينا رمزين مهمين للبحث:
%
: يمثل أي عدد من الأحرف_
: يمثل حرف واحد فقط
هذه العلامات تسمى Wildcards
ويستخدمان في الـ LIKE
لتحدد شكل الجملة التي تريدها
أمثلة على استخدام LIKE مع %
دعنا نرى أمثلة عملية لاستخدام %
مع LIKE
:
البحث عن الطلاب الذين أسماؤهم تبدأ بـ "A"
:
SELECT * FROM Students WHERE name LIKE 'A%';
هنا A%
يعني أي اسم يبدأ بـ "A"
ويتبعه أي شيء
بحيث أن العلامة %
تمثل أي عدد من الأحرف
كأنك تقول A(أي شيء)
النتيجة:
+----+----------------+-----+-----------+----------------------+
| id | name | age | level | email |
+----+----------------+-----+-----------+----------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+----------------+-----+-----------+----------------------+
هنا لدينا فقط الطلاب الذين أسماؤهم تبدأ بحرف A
وهما Ahmed Moustafa
و Ayman Hassan
بالتالي يمكنك تخيل أن A%
كان مجرد قالب يبحث عن أي اسم يبدأ بـ A
ويتبعه أي شيء
وهنا الاسم Ahmed Moustafa
يحقق الشرط لأنه يبدأ بـ A
والجزء المتبقي من الاسم هو hmed Moustafa
الذي تمثله العلامة %
والاسم Ayman Hassan
أيضًا يحقق الشرط لأنه يبدأ بـ A
والجزء المتبقي هو yman Hassan
الذي تمثله العلامة %
البحث عن الطلاب الذين أسماؤهم تنتهي بـ "Ali"
:
SELECT * FROM Students WHERE name LIKE '%Ali';
هنا %Ali
يعني أي اسم ينتهي بـ "Ali"
ويسبقه أي شيء
لأننا وضعنا %
قبل Ali
، أي عدد من الحروف يتبعها كلها
كأنك تقول (أي شيء)Ali
النتيجة:
+----+-----------+-----+--------------+----------------------+
| id | name | age | level | email |
+----+-----------+-----+--------------+----------------------+
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
+----+-----------+-----+--------------+----------------------+
هنا حصنا على طالب واحد فقط وهو Osama Ali
الذي اسمه ينتهي بـ Ali
وهنا نفس الفكرة فالشكل الذي اخترناه %Ali
بالتالي الجزء الذي كان تمثله العلامة %
هو Osama
ثم يتبعها Ali
البحث عن الطلاب الذين أسماؤهم تحتوي على "med"
:
SELECT * FROM Students WHERE name LIKE '%med%';
هنا استخدمنا %
قبل وبعد med
وهذا يعني أي اسم يحتوي على "med"
في أي مكان مهما كان موقعها
كأنك تقول (أي شيء)med(أي شيء)
النتيجة:
+----+--------------+-----+-----------+------------------------+
| id | name | age | level | email |
+----+--------------+-----+-----------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
+----+--------------+-----+-----------+------------------------+
هنا لدينا طالب واحد فقط وهو Mohamed Adel
الذي يحتوي اسمه على med
في منتصف الاسم
وكالامثلة السابقة فـ %med%
هو شكل قالب يبحث عن أي اسم يحتوي على med
في أي مكان
بالتالي الجزء الذي تمثله العلامة %
الأولى هو Moha
ثم يتبعها الجزء med
ثم يتبعها الجزء الذي تمثله العلامة %
الثانية وهو Adel
أمثلة على استخدام LIKE مع _
الآن دعنا نرى أمثلة على استخدام _
للبحث عن حرف واحد فقط
على عكس %
التي كانت تمثل أي عدد من الأحرف، فالعلامة _
تمثل حرف واحد فقط
البحث عن الأسماء التي تبدأ بـ "A"
ويليها حرف واحد ثم "med"
:
SELECT * FROM Students WHERE name LIKE 'A_med%';
هنا A_med%
يعني أي اسم يبدأ بـ "A"
ثم حرف واحد فقط ثم "med"
ثم أي شيء
العلامة _
تمثل حرف واحد بالضبط، بينما %
تمثل أي عدد من الأحرف
يمكنك قراءة A_med%
كالتالي: A(حرف واحد)med(أي شيء)
بالتالي النتيجة ستكون:
+----+----------------+-----+-----------+----------------------+
| id | name | age | level | email |
+----+----------------+-----+-----------+----------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
+----+----------------+-----+-----------+----------------------+
البحث عن الطلاب الذين أسماؤهم الأولى مكونة من 5
أحرف بالضبط:
SELECT * FROM Students WHERE name LIKE '_____ %';
هنا استخدمنا 5
من العلامة _
ثم مسافة ثم %
وهذا يعني أي اسم مكون من 5
ثم مسافة ثم أي شيء
كأنك تقول 5 أحرف بالضبط + مسافة + (أي شيء)
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
هنا لدينا جميع الطلاب الذين أسماؤهم الأولى مكونة من 5
أحرف بالضبط
وهذا لأننا استخدمنا _____
لتمثيل 5
أحرف بالضبط، ثم مسافة، ثم %
لتمثيل أي شيء بعد ذلك
ولاحظ أن الطالب Mohamed Adel
لم يظهر لأنه اسمه مكون من 6
أحرف وليس 5
البحث في مجموعة من القيم باستخدام IN
في بعض الأحيان نريد البحث عن البيانات التي تتطابق مع مجموعة من القيم
فمثلًا نريد جميع الطلاب الذين مستواهم Advanced
أو Intermediate
هنا قد تقول لي يمكننا استخدام OR
للقيام بذلك
SELECT * FROM Students WHERE level = 'Advanced' OR level = 'Intermediate';
وهذا كود سليم وبلا أي مشكلة، لكن هناك طريقة أفضل وأكثر كفاءة
وهي استخدام IN
للبحث في مجموعة من القيم
فالـ IN
يسمح لك بتحديد مجموعة من القيم في شرط واحد
يمكننا استخدام IN
لتبسيط الـ Query
السابقة:
SELECT * FROM Students WHERE level IN ('Advanced', 'Intermediate');
هذا الأمر يعني "أريد الطلاب الذين مستواهم ضمن هذه القائمة"
النتيجة:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
هذا سيعطينا جميع الطلاب الذين مستواهم Advanced
أو Intermediate
أريد جميع الطلاب الذين أعمارهم 20
أو 22
سنة
SELECT * FROM Students WHERE age IN (20, 22);
هذا سيعطينا جميع الطلاب الذين أعمارهم 20
أو 22
سنة
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
استبعاد مجموعة من القيم باستخدام NOT IN
إذا كنت تريد عكس الـ IN
، أي الطلاب الذين لا يحققون هذه القيم، يمكنك استخدام NOT IN
يمكنك البحث عن الطلاب الذين ليس مستواهم Advanced
أو Intermediate
بدلاً من استخدام AND
وكتابة الشرط هكذا level != 'Advanced' AND level != 'Intermediate'
يمكنك استخدام NOT IN
لتبسيط الأمر:
SELECT * FROM Students WHERE level NOT IN ('Advanced', 'Intermediate');
هذا سيعطينا جميع الطلاب الذين مستواهم ليس Advanced
أو Intermediate
النتيجة:
+----+----------------+-----+-----------+----------------------+
| id | name | age | level | email |
+----+----------------+-----+-----------+----------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
+----+----------------+-----+-----------+----------------------+
البحث في نطاق معين باستخدام BETWEEN
عندما تريد البحث عن البيانات ضمن نطاق معين، مثل الطلاب الذين أعمارهم بين 19
و 21
سنة
بدلًا من استخدام AND
وكتابة الشرط هكذا age >= 19 AND age <= 21
يمكنك استخدام BETWEEN
لتبسيط الأمر
فبدلاً من كتابة هذه الـ Query
:
SELECT * FROM Students WHERE age >= 19 AND age <= 21;
يمكنك كتابتها بهذه الطريقة:
SELECT * FROM Students WHERE age BETWEEN 19 AND 21;
هذا الأمر يعني "أريد الطلاب الذين أعمارهم بين 19
و 21
سنة"
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
استبعاد القيم من نطاق معين باستخدام NOT BETWEEN
إذا كنت تريد استبعاد مجموعة من القيم من نطاق معين، فيمكنك استخدام NOT BETWEEN
على سبيل المثال، إذا كنت تريد جميع الطلاب الذين أعمارهم ليست بين 19
و 21
سنة
بدلاً من كتابة الشرط هكذا age < 19 OR age > 21
يمكنك استخدام NOT BETWEEN
:
SELECT * FROM Students WHERE age NOT BETWEEN 19 AND 21;
هذا سيعطينا الطلاب الذين أعمارهم ليست بين 19
و 21
سنة
النتيجة:
+----+--------------+-----+-----------+------------------------+
| id | name | age | level | email |
+----+--------------+-----+-----------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
+----+--------------+-----+-----------+------------------------+
التعامل مع القيم الفارغة NULL
في قواعد البيانات، أحيانًا تكون بعض البيانات فارغة أو غير محددة
هذه القيم تسمى NULL
وهي تختلف عن النص الفارغ ''
أو الرقم صفر 0
فالـ NULL
يعني "لا توجد قيمة" أو "القيمة غير معروفة"
حاليا لا يوجد لدينا أي عمود في جدولنا يحتوي على NULL
، لكن دعنا نضيف بعض البيانات التي تحتوي على NULL
INSERT INTO Students (name, email, age, level) VALUES
('Adam Ibrahim', '[email protected]', NULL, 'Beginner'),
('Ismail Khaled', '[email protected]', 22, NULL),
('Ali Hassan', '[email protected]', NULL, NULL);
الآن لدينا طلاب لديهم أعمار غير محددة أو مستويات غير محددة
+----+-----------------+------+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+------+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 6 | Adam Ibrahim | NULL | Beginner | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
| 8 | Ali Hassan | NULL | NULL | [email protected] |
+----+-----------------+------+--------------+------------------------+
البحث عن القيم الفارغة باستخدام IS NULL
للبحث عن القيم الفارغة، لا يمكنك استخدام =
أو !=
لأن NULL
لا يمكن مقارنته بهذه الطريقة فهو ليس قيمة فعلية
لذلك، يجب استخدام IS NULL
:
SELECT * FROM Students WHERE age IS NULL;
هذا سيعطينا جميع الطلاب الذين عمرهم غير محدد
بالتالي النتيجة ستكون:
+----+--------------+------+-----------+------------------------+
| id | name | age | level | email |
+----+--------------+------+-----------+------------------------+
| 6 | Adam Ibrahim | NULL | Beginner | [email protected] |
| 8 | Ali Hassan | NULL | NULL | [email protected] |
+----+--------------+------+-----------+------------------------+
ملحوظة
: لا تستخدم=
أو!=
أو<>
معNULL
لأنها دائمًا ستعيدfalse
لأنNULL
لا يساوي أي شيء، حتى نفسه بالتالي لو قمت بعملNULL = NULL
ستجدها تعيدfalse
لذلك استخدمIS NULL
أوIS NOT NULL
عندما تتعامل معNULL
من أجل فقط اشباع الفضول، إذا كتبت age = NULL
بدلاً من age IS NULL
النتيجة ستكون:
+----+-----------------+------+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+------+--------------+------------------------+
لا يوجد شيء برغم من أن هناك طلاب أعمارهم NULL
لكن بسبب أننا استخدمنا =
مع NULL
، فستكون النتيجة دائمًا false
لذا استخدم IS NULL
بدلاً من =
عند التعامل مع NULL
البحث عن القيم غير الفارغة باستخدام IS NOT NULL
بالطبع يمكنك أيضًا البحث عن القيم التي ليست NULL
باستخدام IS NOT NULL
SELECT * FROM Students WHERE age IS NOT NULL;
هذا سيعطينا جميع الطلاب الذين عمرهم محدد ولها قيمة
النتيجة ستكون:
+----+-----------------+------+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+------+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
+----+-----------------+------+--------------+------------------------+
كل شيء قلناه عن IS NULL
ينطبق أيضًا على IS NOT NULL
خصوصًا في التعامل مع NULL
بالـ =
أو !=
أو <>
ترتيب النتائج باستخدام ORDER BY
عندما تقوم بعمل أي Query
على البيانات، قد تحتاج إلى ترتيبها بطريقة معينة
مثلاً، تريد عرض الطلاب مرتبين حسب العمر من الأصغر للأكبر، أو حسب الاسم أبجديًا
هنا يأتي دور أمر الـ ORDER BY
الذي يستخدم لترتيب النتائج سواءً بشكل تصاعدي أو تنازلي حسب العمود الذي تحدده
الترتيب التصاعدي
وهو الترتيب من الأصغر للأكبر أو من الأبجدية A إلى Z
وهو الترتيب الافتراضي في الـ SQL
بالتالي عندما تستخدم ORDER BY
بدون تحديد نوع الترتيب، سيتم الترتيب تصاعديًا بشكل افتراضي
لنفترض أننا نريد عرض جميع الطلاب مرتبين حسب العمر من الأصغر للأكبر
نقوم فقط بكتابة ORDER BY
متبوعًا باسم العمود الذي نريد الترتيب حسبه، وهو age
في هذه الحالة:
SELECT * FROM Students ORDER BY age;
هذا الأمر سيعرض الطلاب مرتبين حسب العمر من الأصغر للأكبر
النتيجة:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 6 | Adam Ibrahim | NULL| Beginner | [email protected] |
| 8 | Ali Hassan | NULL| NULL | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
+----+-----------------+-----+--------------+------------------------+
لاحظ أن الطلاب الذين ليس لديهم أعمار أي قيمها NULL
تظهر أولاً في الترتيب
لأنها تعتبر أقل من أي قيمة عددية أخرى في الترتيب
إذا كنت تريد تجاهل القيم NULL
في الترتيب، يمكنك استخدام WHERE
لتصفية النتائج قبل الترتيب:
SELECT * FROM Students WHERE age IS NOT NULL
ORDER BY age;
فقط نستخدم WHERE age IS NOT NULL
لتجاهل الطلاب الذين أعمارهم NULL
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
+----+-----------------+-----+--------------+------------------------+
هنا تم تجاهل الطلاب الذين أعمارهم NULL
وتم ترتيب البقية حسب العمر من الأصغر للأكبر
لو أردت أن توضح أو تأكد أن الترتيب تصاعدي، يمكنك استخدام ASC
:
SELECT * FROM Students WHERE age IS NOT NULL
ORDER BY age ASC;
كلمة ASC
تعني Ascending أي تصاعدي، وهي تخبر الـ SQL
أن يرتب النتائج من الأصغر للأكبر
لكن بما أن الترتيب التصاعدي هو الافتراضي، يمكنك تجاهل ASC
واستخدام ORDER BY age
فقط دون الحاجة لتحديد ASC
الترتيب التنازلي
للترتيب من الأكبر للأصغر، استخدم DESC
بعد اسم العمود في ORDER BY
لتحديد الترتيب التنازلي:
SELECT * FROM Students WHERE age IS NOT NULL
ORDER BY age DESC;
لاحظ أن الـ Query
هنا نفسها السابقة، لكننا أضفنا DESC
بعد age
بدلاً من ASC
لإخبار الـ SQL
أن يرتب النتائج من الأكبر للأصغر
ولاحظ أن DESC
تعني Descending أي تنازلي، وبالتالي هذا سيعرض الطلاب مرتبين حسب العمر من الأكبر للأصغر
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
+----+-----------------+-----+--------------+------------------------+
الترتيب بأكثر من عمود
حسنًا تخيل معين أنك ترتب الطلاب حسب أعمارهم، سيظهر لك طلاب لديهم نفس العمر
مثلاً، Ahmed Moustafa
و Ayman Hassan
كلاهما عمره 20
سنة
هنا تسأل نفسك هل إذا تساوى العمر تريد أن تعطي الأولية للترتيب حسب الاسم ؟
مثلًا Ahmed
يأتي قبل Ayman
أم العكس Ayman
يأتي قبل Ahmed
؟
هنا يمكنك استخدام ORDER BY
مع أكثر من عمود لترتيب النتائج بشكل ثانوي في حالة تساوي العمود الأول
هذا مفيد جداً عندما يكون لديك قيم متشابهة في العمود الأول وتريد ترتيب ثانوي للقيم المتشابهة
SELECT * FROM Students WHERE age IS NOT NULL
ORDER BY age DESC;
هنا نفس الـ Query
السابقة، فقط نرتب الطلاب حسب العمر تنازلياً
لكي اذكرك بشكل النتيجة عندما نرتب حسب العمر تنازلياً
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
+----+-----------------+-----+--------------+------------------------+
الآن ستلاحظ أن لدينا طلاب لديهم نفس العمر، مثل Mohamed Adel
و Ismail Khaled
كلاهما عمره 22
سنة
و Ahmed Moustafa
و Ayman Hassan
كلاهما عمره 20
سنة
هنا نريد أن نرتبهم حسب الإسم في حالة تساوي العمر
بالتالي نضيف عمود name
في جملة ORDER BY
:
SELECT * FROM Students
WHERE age IS NOT NULL
ORDER BY age DESC, name ASC;
هنا نحن نرتب النتائج حسب age
تنازلياً، ثم إذا تساوى العمر نرتب حسب name
تصاعدياً
لاحظ أن كل عمود في ORDER BY
يمكن أن يكون له ترتيب مستقل، سواء تصاعدي ASC
أو تنازلي DESC
فهنا كتبنا age DESC
ثم name ASC
وفصلنا بينهما بـ ,
على أي حال النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
+----+-----------------+-----+--------------+------------------------+
لاحظ أن Ismail Khaled
يأتي أولاً لأنه اسمه يبدأ بحرف I
، بينما Mohamed Adel
يأتي بعده لأنه اسمه يبدأ بحرف M
وقيمة الحرف I
في الـ ASCII
تساوي 73
بينما قيمة الحرف M
تساوي 77
بالتالي لأننا رتبنا حسب name
تصاعدياً من الأصغر للأكبر، فـ I
أصغر من M
فأتى Ismail Khaled
أولاً
لو أردنا أن نرتب حسب name
تنازلياً، يمكننا تغيير ASC
إلى DESC
:
SELECT * FROM Students
WHERE age IS NOT NULL
ORDER BY age DESC, name DESC;
النتيجة ستكون:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
| 7 | Ismail Khaled | 22 | NULL | [email protected] |
| 4 | Kamal Mahmoud | 21 | Beginner | [email protected] |
| 5 | Ayman Hassan | 20 | Advanced | [email protected] |
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
+----+-----------------+-----+--------------+------------------------+
لاحظ أن Mohamed Adel
أتى أولاً لأنه اسمه يبدأ بحرف M
، بينما Ismail Khaled
يأتي بعده لأنه اسمه يبدأ بحرف I
لأننا رتبنا حسب name
تنازلياً، فـ M
أكبر من I
، فأتى Mohamed Adel
أولاً
وأيضًا Ayman Hassan
أتى أولًَا قبل Ahmed Moustafa
لأن قيمة y
تساوي 121
في الـ ASCII
وهي أكبر من قيمة h
التي تساوي 104
ملحوظة: جدول الـ
ASCII
هو جدول به128
حرفًا ورمزًا وكل واحد منها يقابله عدد معين
فمثلًا الحرفA
يقابله الرقم65
والحرفB
يقابله الرقم66
والحرفC
يقابله الرقم67
وهكذا
يمكنك الاطلاع على جدول الـASCII
من هنا
تحديد عدد النتائج باستخدام LIMIT
في التطبيقات الحقيقية، قد تحتوي الجداول على آلاف أو حتى ملايين البيانات
وحتى لو استخدمت WHERE
لتصفية النتائج، قد تظل النتائج كبيرة جدًا
تخيل أن جدول الطلاب يحتوي على 50000
طالب، وأنت تريد عرض أول 5
طلاب فقط ماذا ستفعل ؟
أول مثلًا قمت بترتيبهم بحسب أعمارهم وتريد عرض أكبر طالب سناً
هنا يأتي دور الـ LIMIT
الذي يخبر الـ SQL
أن تحضر عدد محدد من النتائج فقط
وهذا يوفر الوقت والذاكرة ويحسن الأداء بشكل كبير وكل هذه الكلمات الرنانة
SELECT * FROM Students LIMIT 3;
هذا الأمر ببساطة يعني "أحضر لي فقط أول 3
طلاب من الجدول"
النتيجة:
+----+-----------------+-----+--------------+------------------------+
| id | name | age | level | email |
+----+-----------------+-----+--------------+------------------------+
| 1 | Ahmed Moustafa | 20 | Beginner | [email protected] |
| 2 | Osama Ali | 19 | Intermediate | [email protected] |
| 3 | Mohamed Adel | 22 | Advanced | [email protected] |
+----+-----------------+-----+--------------+------------------------+
ملحوظة
: الـLIMIT
يحضر النتائج بالترتيب الذي تم إضافة البيانات في الجدول في حالة إذا لم تستخدمORDER BY
بالطبع
بالتالي الاستخدام الأكثر شيوعاً هو دمج LIMIT
مع ORDER BY
للحصول على نتائج مرتبة ثم تحديد عدد النتائج
ويمكنك دمجهم مع WHERE
لتصفية النتائج قبل تطبيق LIMIT
فمثًا أحضر لي أكبر 3
طلاب سناً:
SELECT name, age FROM Students
WHERE age IS NOT NULL
ORDER BY age DESC
LIMIT 3;
النتيجة:
+-----------------+-----+
| name | age |
+-----------------+-----+
| Mohamed Adel | 22 |
| Ismail Khaled | 22 |
| Kamal Mahmoud | 21 |
+-----------------+-----+
هنا أحضرنا أكبر 3
طلاب سناً بترتيب تنازلي حسب العمر
ولاحظ أننا استخدمنا LIMIT
لتحديد عدد النتائج المعروضة إلى 3
فقط لكي لا نحضر كل البيانات في الجدول
الآن مثال أخر أحضر أصغر طالب سناً في المستوى Beginner
:
SELECT name, age FROM Students
WHERE age IS NOT NULL AND level = 'Beginner'
ORDER BY age ASC
LIMIT 1;
النتيجة:
+-----------------+-----+
| name | age |
+-----------------+-----+
| Ahmed Moustafa | 20 |
+-----------------+-----+
الخاتمة
أظن أننا سنكتفي بهذا القدر لكي لا نطيل المقالة أكثر من هذا
يكفي أنك فهمت الأساسيات المهمة في الـ SELECT
وكيفية التعامل مع البيانات
وتعرفنا على أوامر كثيرة وتطبيقنا عليهم بأمثلة عملية
وبالطبع قد تكون هناك تفاصيل تعمدت عدم ذكرها لكي لا نثقل عليك في البداية
وأوامر لم نتطرق لها لكي لا نطيل الشرح
لكن لا تقلق كل شيء سيأتي في وقته، في المقالات القادمة سنغطي أو من خلال تعلمك من ممارستك
ملخص ما تعلمناه في هذه المقالة
- قراءة البيانات بـ
SELECT *
لقراءة كل الأعمدة - قراءة أعمدة محددة بـ
SELECT column1, column2
- تصفية البيانات بـ
WHERE
وعوامل المقارنة (=
,>
,<
,!=
) - ربط الشروط بـ
AND
وOR
واستخدام الأقواس - البحث عن الجمل أو النصوص بـ
LIKE
مع%
و_
- البحث في مجموعة من القيم بـ
IN
وNOT IN
- البحث في نطاق معين من القيم بـ
BETWEEN
- التعامل مع القيم الفارغة بـ
IS NULL
وIS NOT NULL
- ترتيب النتائج بـ
ORDER BY ASC/DESC
- الترتيب بعدة أعمدة لترتيب ثانوي
- تحديد عدد النتائج بـ
LIMIT
في المقالات القادمة، سنستكمل تعلمنا عن الـ SQL
ونتعلم كيف نعدل القيم بـ UPDATE
وكيف نحذف البيانات بـ DELETE