العامل LIKE
العامل LIKE يستخدم عند الحاجة لتخصيص البحث في العامود الذي يحتوي على قيم نصية.
كمثال بسيط, في حال أراد المستخدم البحث عن كل كتاب عنوانه يتضمن كلمة 'Hero' يمكنك استخدام العامل LIKE مع الأمر SELECT لتحدد ذلك.
الشكل العام لإستخدامه
SELECT column1, column2, ...
FROM table_name
WHERE column_name LIKE pattern;
مكان الكلمة
column_nameنضع إسم العامود الذي يحتوي على قيم نصية و التي نريد تخصيص البحص فيها.مكان الكلمة
patternنضع نص يقال له نمط ( Pattern ) لأنه يحتوي على رموز تمثل الطريقة التي سيتم فيها البحث.
الأحرف و الرموز التي تستخدم لكتابة الأنماط
الأحرف و الرموز التي نضعها في أي نمط يقال لها Wildcards.
قد تختلف قليلاً الأحرف و الرموز التي نضعها في الأنماط من قاعدة بيانات لأخرى و لكن أغلبها متشابه.
في الجدول التالي وضعنا الأحرف و الرموز التي تستخدم في كتابة الأنماط مع تحديد قواعد البيانات التي تستخدم فيها.
| الرمز | إستخدامه |
|---|---|
% |
يستخدم في حال عدم الإكتراث ما إذا كان يوجد شيء أم لا. بالنسبة لقواعد البيانات التي يمكن استخدامه فيها فهي MySQL / SQL Server / Oracle. مثال: 'Hello*'هذا النمط يقصد منه أننا نريد أن يكون الحقل النصي يبدأ بكلمة Hello و لا يهم إن كان يوجد شيء بعدها أم لا. |
* |
يستخدم في حال عدم الإكتراث ما إذا كان يوجد شيء أم لا. بالنسبة لقواعد البيانات التي يمكن استخدامه فيها فهي Access. مثال: 'Hello*'هذا النمط يقصد منه أننا نريد أن يكون الحقل النصي يبدأ بكلمة Hello و لا يهم إن كان يوجد شيء بعدها أم لا. |
_ |
يستخدم للإشارة إلى وجوب وجود أي حرف في المكان الذي يتم وضعه. بالنسبة لقواعد البيانات التي يمكن استخدامه فيها فهي MySQL / SQL Server / Oracle. مثال: 'm_n'هذا النمط يقصد منه أننا نريد أن يكون الحقل النصي يبدأ بحرف m و يوجد حرفين بعده فقط مثل men - man - msn. |
? |
يستخدم للإشارة إلى وجوب وجود أي حرف في المكان الذي يتم وضعه. بالنسبة لقواعد البيانات التي يمكن استخدامه فيها فهي Access. مثال: 'm?n'هذا النمط يقصد منه أننا نريد أن يكون الحقل النصي يبدأ بحرف m و يوجد حرفين بعده فقط مثل men - man - msn. |
تجهيز قاعدة البيانات التي سنطبق عليها
قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها harmash و تنشئ فيها جدول إسمه users يحتوي على بيانات 10 مستخدمين.
الإستعلام
-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
DROP DATABASE IF EXISTS harmash;
-- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
CREATE DATABASE harmash;
-- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
USE harmash;
-- يتألف من 4 أعمدة users هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50),
last_name VARCHAR(50),
country VARCHAR(50)
);
-- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 مستخدمين
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة
-- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة
INSERT INTO users VALUES (null, "Rami", "Masri", "Lebanon");
INSERT INTO users VALUES (null, "Ahmad", "Naji", "Syria");
INSERT INTO users VALUES (null, "Hanan", "Mostafa", "KSA");
INSERT INTO users VALUES (null, "Saly", "Jawhar", "Lebanon");
INSERT INTO users VALUES (null, "Mhamad", "Harmush", "Lebanon");
INSERT INTO users VALUES (null, "Hamad", "Akel", "Syria");
INSERT INTO users VALUES (null, "Abdullah", "Helmi", "Egypt");
INSERT INTO users VALUES (null, "Rashed", "Masri", "Oman");
INSERT INTO users VALUES (null, "Majed", "Alali", "Yaman");
INSERT INTO users VALUES (null, "Rayan", "Kasabi", "KSA");
بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدول users بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.
البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول users.
| id | first_name | last_name | country |
|---|---|---|---|
| 1 | Rami | Masri | Lebanon |
| 2 | Ahmad | Naji | Syria |
| 3 | Hanan | Mostafa | KSA |
| 4 | Saly | Jawhar | Lebanon |
| 5 | Mhamad | Harmush | Lebanon |
| 6 | Hamad | Akel | Syria |
| 7 | Abdullah | Helmi | Egypt |
| 8 | Rashed | Masri | Oman |
| 9 | Majed | Alali | Yaman |
| 10 | Rayan | Kasabi | KSA |
أمثلة شاملة على كتابة الأنماط
المثال الأول
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name يبدأ بحرف A.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE first_name LIKE 'A%'; -- A يبدأ بالحرف first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 2 | Ahmad | Naji | Syria |
| 7 | Abdullah | Helmi | Egypt |
المثال الثاني
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name ينتهي الحرفين ad.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE first_name LIKE '%ad'; -- ad ينتهي بالحرفين first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 2 | Ahmad | Naji | Syria |
| 5 | Mhamad | Harmush | Lebanon |
| 6 | Hamad | Akel | Syria |
المثال الثالث
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name يبدأ بحرف M و ينتهي بحرف D.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE first_name LIKE 'M%D'; -- D و ينتهي بالحرف M يبدأ بالحرف first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 5 | Mhamad | Harmush | Lebanon |
| 9 | Majed | Alali | Yaman |
المثال الرابع
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name يتضمن الحرفين am و لا يهم إن كانا موجودين في البداية أو في الوسط أو في النهاية.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE first_name LIKE '%am%'; -- و لا يهم إن كانا موجودين في البداية أو في الوسط أو في النهاية am يتضمن الحرفين first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 1 | Rami | Masri | Lebanon |
| 5 | Mhamad | Harmush | Lebanon |
| 6 | Hamad | Akel | Syria |
المثال الخامس
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name يبدأ بحرف A أو R.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE (first_name LIKE 'A%' OR first_name LIKE 'R%'); -- R أو الحرف A يبدأ بالحرف first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 1 | Rami | Masri | Lebanon |
| 2 | Ahmad | Naji | Syria |
| 7 | Abdullah | Helmi | Egypt |
| 8 | Rashed | Masri | Oman |
| 10 | Rayan | Kasabi | KSA |
المثال السادس
الإستعلام التالي يجلب جميع الأسطر التي فيها الحقل first_name لا يبدأ بالحرف A.
الإستعلام
SELECT * FROM users -- users هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE first_name NOT LIKE 'A%'; -- A لا يبدأ بالحرف first_name التي فيها الحقل
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | first_name | last_name | country |
|---|---|---|---|
| 1 | Rami | Masri | Lebanon |
| 3 | Hanan | Mostafa | KSA |
| 4 | Saly | Jawhar | Lebanon |
| 5 | Mhamad | Harmush | Lebanon |
| 6 | Hamad | Akel | Syria |
| 8 | Rashed | Masri | Oman |
| 9 | Majed | Alali | Yaman |
| 10 | Rayan | Kasabi | KSA |
مفهوم الإستعلامات المتدخلة
الإستعلام العادي الذي لا يحتوي على أوامر متداخلة يقال له Query فقط.
بينما الإستعلام الذي يحتوي على أوامر متداخلة مثل أمر SELECT بداخله أمر SELECT فهنا يقال لهذا الإستعلام Sub Query أو Nested Query أو Inner Query.
الإستعلامات المتداخلة مهمة جداً و هي منطق في العمل نطبقه عند الحاجة لإجراء إحصاءات محددة على أساسسها نقوم بجلب القيم, تعديلها, أو حذفها.
في هذا الدرس لن تتعلم أوامر جديدة في SQL بل ستتعلم المنطق الذي نتبعه لكتابة إستعلامات متداخلة خطوة خطوة.
كتابة إستعلامات متداخلة يعتبر أصعب شيء قد تتعلمه في قواعد البيانات و قد تحتاج وقت حتى تعتاد عليه و تفهم كيف تفعله بنفسك.
لذا حاول متابعة الدرس بهدوء و تركيز تام و شاهد الفيديوهات الموضوعة ضمن الأمثلة لأنها ستساعدك كثيراً في فهم الطريقة التي تم فيها كتابة الإستعلامات.
أولوية تنفيذ الإستعلامات المتداخلة
عند وضع الإستعلامات بداخل بعضها البعض, يتم تنفيذ الإستعلامات الداخلية و من ثم الإستعلامات الخارجية.
كمثال بسيط, تخيل أن الإستعلام مكتوب على هذا النحو.
SELECT * FROM users
WHERE salary = (SELECT MAX(salary) FROM users);
هنا سيتم حساب ناتج الإستعلام الداخلي و يتم وضع جوابه مكانه.
فمثلاً في حال كان ناتج الإستعلام الداخلي هو 1500 فإن الإستعلام سيصبح كأنه كالتالي بالضبط.
SELECT * FROM users
WHERE salary = 1500;
الآن بعد أن أصبح الإستعلام لا يحتوي على أي أوامر متداخلة, سيتم إعطاءك الجواب النهائي.
ملاحظة
أي إستعلام داخلي يجب أن تضعه بين قوسين ( ) لأن أولية التنفيذ تقررها قاعدة البيانات نسبةً للأقواس.
و بالطبع في حال كان يوجد أكثر من إستعلام داخلي, سيتم تنفيذ أعمق إستعلام بينهم في البداية رجوعاً للإستعلام الأساسي الذي ينتظر نتائج كل الإستعلام الموضوعة فيه حتى يتنفذ كما في المال السابق.
تجهيز قاعدة البيانات التي سنطبق عليها
قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها harmash و تنشئ فيها جدول إسمه scientists يحتوي على بيانات 10 علماء.
الإستعلام
-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
DROP DATABASE IF EXISTS harmash;
-- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
CREATE DATABASE harmash;
-- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
USE harmash;
-- يتألف من 5 أعمدة scientists هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE scientists (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
salary DECIMAL(7,2),
country VARCHAR(50),
continent VARCHAR(50)
);
-- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 علماء
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة
-- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة
INSERT INTO scientists VALUES (null, "Ahmad", 4200, "KSA", "Asia");
INSERT INTO scientists VALUES (null, "Rami", 2750, "Egypt", "Africa");
INSERT INTO scientists VALUES (null, "Said", 3900, "Lebanon", "Asia");
INSERT INTO scientists VALUES (null, "Noura", 3150, "Algeria", "Africa");
INSERT INTO scientists VALUES (null, "Amani", 2950, "Morocco", "Africa");
INSERT INTO scientists VALUES (null, "Mhamad", 3700, "Lebanon", "Asia");
INSERT INTO scientists VALUES (null, "Wissam", 3550, "Oman", "Asia");
INSERT INTO scientists VALUES (null, "Mostafa", 4120, "Qatar", "Asia");
INSERT INTO scientists VALUES (null, "Houssam", 6800, "Germany", "Europe");
INSERT INTO scientists VALUES (null, "Jana", 7500, "Canada", "North America");
بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدول scientists بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.
البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول scientists.
| id | name | salary | country | continent |
|---|---|---|---|---|
| 1 | Ahmad | 4200.00 | KSA | Asia |
| 2 | Rami | 2750.00 | Egypt | Africa |
| 3 | Said | 3900.00 | Lebanon | Asia |
| 4 | Noura | 3150.00 | Algeria | Africa |
| 5 | Amani | 2950.00 | Morocco | Africa |
| 6 | Mhamad | 3700.00 | Lebanon | Asia |
| 7 | Wissam | 3550.00 | Oman | Asia |
| 8 | Mostafa | 4120.00 | Qatar | Asia |
| 9 | Houssam | 6800.00 | Germany | Europe |
| 10 | Jana | 7500.00 | Canada | North America |
أمثلة شاملة على كتابة إستعلامات متداخلة
المثال الأول
الإستعلام التالي يعرض جميع معلومات الموظف الذي ينال أعلى أجر.
هنا يجب معرفة أكبر راتب يتم إعطاؤه للموظفين, بعد معرفته يمكننا إحضار معلومات كل موظف يملك نفس هذا الراتب.
الإستعلام
SELECT * FROM scientists -- scientists هنا قمنا بعرض بيانات جميع الأسطر الموجودة في الجدول
WHERE salary = (SELECT MAX(salary) FROM scientists) -- (scientists موجود في الجدول salary أعلى) يساوي salary التي تملك
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| id | name | salary | country | continent |
|---|---|---|---|---|
| 10 | Jana | 7500.00 | Canada | North America |
المثال الثاني
الإستعلام التالي يعرض أسماء و رواتب العلماء الذين ينالون راتب لا يتجاوز متوسط الرواتب التي يتم إعطاءها للموظفين.
هنا يجب معرفة متوسط الرواتب التي يتم إعطاءها للموظفين, بعد معرفته يمكننا إحضار أسماء و رواتب العلماء الذين يملكون راتب أقل منه.
الإستعلام
SELECT name, salary FROM scientists -- scientists هنا قمنا بعرض إسم و راتب كل عالم في الجدول
WHERE salary < (SELECT AVG(salary) FROM scientists) -- (scientists موجود في الجدول salary متوسط كل) أقل من salary يملك
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| name | salary |
|---|---|
| Ahmad | 4200.00 |
| Rami | 2750.00 |
| Said | 3900.00 |
| Noura | 3150.00 |
| Amani | 2950.00 |
| Mhamad | 3700.00 |
| Wissam | 3550.00 |
| Mostafa | 4120.00 |
المثال الثالث
الإستعلام التالي يعرض إسم أكثر قارة تم إحضار علماء منها.
هنا يجب معرفة عدد العلماء الموجودين في كل قارة.
بعدها يجب معرفة أكبر عدد علماء تم إيجاده في قارة.
بعدها يجب طباعة إسم و عدد علماء كل قارة عدد علمائها يساوي عدد العلماء الأكبر الذي عرفناه.
الإستعلام
الطريقة التالية تعمل مع جميع قواعد البيانات.
SELECT continent, COUNT(id) AS total
FROM scientists
GROUP BY continent
HAVING total = (SELECT MAX(t.total) AS max_count
FROM (SELECT continent, COUNT(id) AS total
FROM scientists
GROUP BY continent) AS t)
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.
إذا كنت تستخدم قواعد بيانات MySQL يمكنك كتابة الإستعلام نفسه كالتالي.
SELECT continent, COUNT(id) AS total
FROM scientists
GROUP BY continent
HAVING total = (SELECT COUNT(id) AS max_count
FROM scientists
GROUP BY continent
ORDER BY max_count DESC
LIMIT 1);
إذا كنت تستخدم قواعد بيانات SQL Server / Access يمكنك كتابة الإستعلام نفسه كالتالي.
SELECT continent, COUNT(id) AS total
FROM scientists
GROUP BY continent
HAVING total = (SELECT TOP 1 COUNT(id) AS max_count
FROM scientists
GROUP BY continent
ORDER BY max_count DESC);
إذا كنت تستخدم قواعد بيانات Oracle يمكنك كتابة الإستعلام نفسه كالتالي.
SELECT continent, COUNT(id) AS total
FROM scientists
GROUP BY continent
HAVING total = (SELECT COUNT(id) AS max_count
FROM scientists
WHERE ROWNUM <= 1
GROUP BY continent
ORDER BY max_count DESC);
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
| continent | total |
|---|---|
| Asia | 5 |