مفهوم وضع الشروط على الحقول التي تم تجميعها
في البداية المقصود من هذا الأمر هو وضع شروط على النتيجة التي سنحصل عليها بعد أن قمنا بتجميع الحقول و إجراء إحصاء ما.
بمعنى أخر, بعد أن تقوم بتجميع قيم الحقول بواسطة الكلمة GROUP BY يمكنك وضع شرط لفلترة النتيجة التي تم تجميعها أيضاً.
كمثال بسيط عن الحاجة لإعادة الفلترة بعد تجميع القيم, في حال كنت تريد إجراء إحصاء لمعرفة متوسط رواتب موظفي الشركة في كل بلد, و بعد معرفة متوسط الرواتب في كل بلد تريد معرفة أي بلدان تعطي موظفيها متوسط راتب يتجاوز 800 دولار.
لفلترة النتيجة التي حصلنا عليها بالأساس بعد أن قمنا بتجميع الحقول بواسطة الكلمة GROUP BY نضع الكلمة HAVING و بعدها الشرط الذي سيقوم بفلترة النتيجة أكثر.
الشكل العام لتجميع الحقول
إذا كنت ستجمع الحقول فقط و بعدها تضع الشرط الذي سيفلتر النتيجة, شكل الإستعلام سيكون كالتالي.
SELECT column_name(s)
FROM table_name
GROUP BY column_name(s)
HAVING condition;
إذا كنت ستجمع الحقول و تضع شروط على القيم التي سيتم تجميعها من الأساس, و بعدها تنوي وضع شرط لفلترة النتيجة و في النهاية تريد ترتيب النتيجة النهائية, شكل الإستعلام سيكون كالتالي.
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);
مكان الكلمة
table_nameنضع إسم الجدول الذي يحتوي على الحقول التي ننوي تجميعها و إجراء إحصاء عليها.بعد الكلمة
WHEREيمكننا وضع شروط على القيم التي سيتم تجميعها من الأساس.بعد الكلمة
HAVINGيمكننا وضع شروط لفلترة النتيجة النهائية التي سيتم إرجاعها.بعد الكلمة
GROUP BYنضع إسم كل عامود نريد أن يتم تجميع القيم بناءاً عليه.
تجهيز قاعدة البيانات التي سنطبق عليها
قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها harmash و تنشئ فيها جدول إسمه employees يحتوي على بيانات 10 موظفين.
الإستعلام
-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
DROP DATABASE IF EXISTS harmash;
-- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
CREATE DATABASE harmash;
-- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
USE harmash;
-- يتألف من 5 أعمدة employees هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE employees (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
gender VARCHAR(20),
country VARCHAR(50),
salary DECIMAL(7,2)
);
-- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 موظفين
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- مكان كل حقل لن نقوم بوضع قيمة فيه null بما أننا لم نحدد أسماء الأعمدة التي سنملأها لاحظ أننا مجبورين على وضع كلمة
-- الموضوعة في بداية كل أمر سيتم إستبدالها بترقيم تلقائي من قبل قاعدة البيانات null و لا تنسى أن الكلمة
INSERT INTO employees VALUES (null, "rami", "male", "Lebanon", 700);
INSERT INTO employees VALUES (null, "ahmad", "male", "Syria", 800);
INSERT INTO employees VALUES (null, "hanan", "female", "KSA", 750);
INSERT INTO employees VALUES (null, "saly", "female", "Lebanon", 650);
INSERT INTO employees VALUES (null, "samir", "male", "Egypt", 600);
INSERT INTO employees VALUES (null, "hamad", "male", "KSA", 700);
INSERT INTO employees VALUES (null, "abdullah", "male", "KSA", 800);
INSERT INTO employees VALUES (null, "rashed", "male", "Oman", 900);
INSERT INTO employees VALUES (null, "majed", "male", "Yaman", 820);
INSERT INTO employees VALUES (null, "malak", "female", "Morocco", 860);
بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدول employees بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.
البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول employees.
| id | user | gender | country | salary |
|---|---|---|---|---|
| 1 | rami | male | Lebanon | 700.00 |
| 2 | ahmad | male | Syria | 800.00 |
| 3 | hanan | female | KSA | 750.00 |
| 4 | saly | female | Lebanon | 650.00 |
| 5 | samir | male | Egypt | 600.00 |
| 6 | hamad | male | KSA | 700.00 |
| 7 | abdullah | male | KSA | 800.00 |
| 8 | rashed | male | Oman | 900.00 |
| 9 | majed | male | Yaman | 820.00 |
| 10 | malak | female | Morocco | 860.00 |
أمثلة حول وضع شروط بعد تجميع قيم الأعمدة
المثال الأول
الإستعلام التالي يقوم بعرض متوسط الرواتب الذي يتم دفعه للموظفين من كل بلد.
ما فعلناه لإجراء هذا الإحصاء هو تجميع أسماء البلدان الموجودة في الحقل country بواسطة الكلمة GROUP BY.
بعدها قمنا باستخدام الدالة AVG() لحساب متوسط رواتب الموظفين الموجودين في كل مجموعة, أي متوسط الموظفين الذين عندهم نفس قيمة الحقل country.
ملاحظة: في هذا الإستعلام لم نقم بفلترة النتيجة التي سترجع بل عرضناها كما هي.
الإستعلام
الإستعلام التالي هو ما يجب كتابته بالضبط للحصول على الإحصاء المطلوب.
SELECT country, AVG(salary) -- country سيتم حسابه بعد أن يتم تجميع قيم الحقل salary متوسط الحقول
FROM employees
GROUP BY country; -- على أساسهم AVG() سيتم تنفيذ الدالة country بعد أن يتم تجميع القيم الموجودة في العامود
نفس الإستعلام السابق و لكننا قمنا بتغيير أسماء الأعمدة و طريقة ظهور متوسط الرواتب حتى تظهر النتيجة النهائية بشكل أوضح و مفهوم.
SELECT
country AS 'country',
FORMAT(AVG(salary), 2) AS 'Average Salary'
FROM
employees
GROUP BY
country;
سنحصل على النتيجة التالية عند تنفيذ الإستعلام الذي غيّرنا أسماء أعمدته.
| Country | Average Salary |
|---|---|
| Egypt | 600.00 |
| KSA | 750.00 |
| Lebanon | 675.00 |
| Morocco | 860.00 |
| Oman | 900.00 |
| Syria | 800.00 |
| Yaman | 820.00 |
المثال الثاني
الإستعلام التالي يقوم بعرض متوسط الرواتب الذي يتم دفعه للموظفين من كل بلد و الذي يتجاوز 800 دولار.
ما فعلناه لإجراء هذا الإحصاء هو تجميع أسماء البلدان الموجودة في الحقل country بواسطة الكلمة GROUP BY.
بعدها قمنا باستخدام الدالة AVG() لحساب متوسط رواتب الموظفين الموجودين في كل مجموعة, أي متوسط الموظفين الذين عندهم نفس قيمة الحقل country.
بعدها قمنا بفلترة النتيجة لعرض متوسط البلدان التي يتجاوز متوسط رواتب الموظفين فيها 800$, و فعلنا ذلك من خلال وضع شرط بواسطة الكلمة HAVING حددنا فيه أننا نريد عرض الأسطر التي فيها salary أكبر من 800.
الإستعلام
الإستعلام التالي هو ما يجب كتابته بالضبط للحصول على الإحصاء المطلوب.
SELECT country, AVG(salary) -- country سيتم حسابه بعد أن يتم تجميع قيم الحقل salary متوسط الحقول
FROM employees
GROUP BY country -- على أساسهم AVG() سيتم تنفيذ الدالة country بعد أن يتم تجميع القيم الموجودة في العامود
HAVING AVG(salary) > 800; -- أكبر من 800 فقط salary النتيجة النهائية سيتم عرض الأسطر التي تحتوي على متوسط
نفس الإستعلام السابق و لكننا قمنا بتغيير أسماء الأعمدة و طريقة ظهور متوسط الرواتب حتى تظهر النتيجة النهائية بشكل أوضح و مفهوم.
SELECT
country AS 'Country',
FORMAT(AVG(salary), 2) AS 'Average Salary'
FROM
employees
GROUP BY
country
HAVING
AVG(salary) > 800;
سنحصل على النتيجة التالية عند تنفيذ الإستعلام الذي غيّرنا أسماء أعمدته.
| Country | Average Salary |
|---|---|
| Morocco | 860.00 |
| Oman | 900.00 |
| Yaman | 820.00 |
طريقة نسخ البيانات من جدول لآخر
نسخ البيانات من جدول لآخر أمر سهل للغاية لأنه مجرد دمج للأمر SELECT الذي نستخدمه للحصول على البيانات من الجداول مع الأمر INSERT INTO الذي نستخدمه لإضافة البيانات في أي جدول.
لنسخ البيانات من جدول لآخر يجب أن يكون نوع الأعمدة التي سيتم النسخ منها متطابق مع نوع الأعمدة التي سيتم النسخ إليها.
عند نسخ البيانات من جدول لآخر تستطيع تحديد الأسطر و الحقول التي سيتم نسخها, أي لست مجبر على نسخ كل بيانات الجدول في جدول آخر.
بالإضافة إلى ذلك, فإن نسخ القيم من جدول لآخر لا يؤثر إطلاقاً على القيم الموجودة في الجدول الذي سيتم النسخ إليه.
نسخ البيانات قد يكون مفيد أيضاً حين تتعامل مع عدة جداول مترابطة و تريد دمجها مع بعضها في جدول جديد لعرضها بشكل مفهوم و مرتب.
لا تفكر بهذه النقطة بالتحديد الآن, لأن هذا الأمر سيمر معك في دروس لاحقة.
الشكل العام لتجميع الحقول
إذا كان الجدولين متطابقين في الشكل, شكل الإستعلام سيكون كالتالي.
INSERT INTO table2
SELECT * FROM table1
WHERE condition;
إذا كان الجدولين غير متطابقين أو تريد تحديد الأعمدة التي سيتم النسخ منها و إليها, شكل الإستعلام سيكون كالتالي.
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1, column2, column3, ...
FROM table1
WHERE condition;
مكان الكلمة
table1نضع إسم الجدول الذي سننسخ البيانات منها.مكان الكلمة
table2نضع إسم الجدول الذي سننسخ البيانات فيه.بعد الكلمة
WHEREيمكننا وضع شروط لتحديد القيم التي سيتم نسخها من الجدولtable1.
تجهيز قاعدة البيانات التي سنطبق عليها
قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها harmash و تنشئ فيها التالي:
جدول إسمه
table1يحتوي على بيانات 5 أسطر.جدول إسمه
table2شكله مطابق تماماً للجدولtable1و لكنه فارغ.
الإستعلام
-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
DROP DATABASE IF EXISTS harmash;
-- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
CREATE DATABASE harmash;
-- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
USE harmash;
-- يتألف من 5 أعمدة table1 هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE table1 (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
gender VARCHAR(20),
country VARCHAR(50),
salary DECIMAL(7,2)
);
-- table1 أعمدته متطابقة مع أعمدة الجدول table2 هنا قمنا بإنشاء جدول جديد إسمه
-- أيضاً لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE table2 (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
gender VARCHAR(20),
country VARCHAR(50),
salary DECIMAL(7,2)
);
-- table1 هنا قمنا بإضافة 5 أسطر في الجدول
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- مكان كل حقل لن نقوم بوضع قيمة فيه null بما أننا لم نحدد أسماء الأعمدة التي سنملأها لاحظ أننا مجبورين على وضع كلمة
-- الموضوعة في بداية كل أمر سيتم إستبدالها بترقيم تلقائي من قبل قاعدة البيانات null و لا تنسى أن الكلمة
INSERT INTO table1 VALUES (null, "rami", "male", "Lebanon", 700);
INSERT INTO table1 VALUES (null, "ahmad", "male", "Syria", 800);
INSERT INTO table1 VALUES (null, "hanan", "female", "KSA", 750);
INSERT INTO table1 VALUES (null, "saly", "female", "Lebanon", 650);
INSERT INTO table1 VALUES (null, "samir", "male", "Egypt", 600);
بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدولين table1 و table2 بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.
البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول table1.
| id | user | gender | country | salary |
|---|---|---|---|---|
| 1 | rami | male | Lebanon | 700.00 |
| 2 | ahmad | male | Syria | 800.00 |
| 3 | hanan | female | KSA | 750.00 |
| 4 | saly | female | Lebanon | 650.00 |
| 5 | samir | male | Egypt | 600.00 |
شكل الجدول table2 الذي لا يحتوي على أي بيانات.
| id | user | gender | country | salary |
|---|---|---|---|---|
أمثلة حول نسخ البيانات من جدول و إضافتها في جدول آخر
المثال الأول
الإستعلام التالي يقوم بنسخ كل القيم الموجودة في الجدول table1 و يضيفها في الجدول table2 و من ثم يقوم بعرض البيانات التي وضعها في الجدول table2.
الإستعلام
INSERT INTO table2 -- table2 هنا قمنا بتحديد أنه سيتم وضع البيانات المنسوخة في الجدول
SELECT * FROM table1; -- table1 هنا قمنا بتحديد أنه سيتم نسخ كل بيانات الجدول
SELECT * FROM table2; -- table2 هنا قمنا بعرض كل البيانات التي أصبح يحتويها الجدول
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
لاحظ أن الجدول table2 أصبح يحتوي على نفس البيانات الموجودة في الجدول table1.
| id | user | gender | country | salary |
|---|---|---|---|---|
| 1 | rami | male | Lebanon | 700.00 |
| 2 | ahmad | male | Syria | 800.00 |
| 3 | hanan | female | KSA | 750.00 |
| 4 | saly | female | Lebanon | 650.00 |
| 5 | samir | male | Egypt | 600.00 |
إنتبه
بالنسبة للحقل id فقد تم نسخ قيمه أيضاً لأن الجدول table2 لم يكن يتضمن أي قيمة مشابهة و لو كان يتضمن قيمة واحدة مشابهة لما تنفذ الإستعلام.
إذاً في حال حاولت تنفيذ الإستعلام السابق مجدداً بهدف إضافة كل قيم الجدول table1 من جديد في الجدول table2 سيظهر لك خطأ يخبرك بأنه لا يمكن تنفيذ الإستعلام لأنه من أول سطر حاولت إضافته إتضح لهم أن رقم التعرفة id الذي تحاول إضافته في الجدول table2 هو رقم موجود في الأساس به.
إذا قمت بتنفيذ الإستعلام السابق من جديد سيظهر لك الخطأ Duplicate entry '1' for key 'PRIMARY' و الذي يعني ما قلناه بالضبط.
المثال الثاني
الإستعلام التالي يقوم بنسخ كل القيم الموجودة في الجدول table1 باستثناء القيم الموضوعة في العامود id.
ما فعلناه هنا, هو ترك قاعدة البيانات تقوم بإعطاء أرقام تعرفة id لوحدها بشكل تلقائي لكل سطر يتم إضافته لأن نوع العامود بالأساس هو AUTO_INCREMENT و هكذا سنتمكن من نسخ كل القيم من جديد في الجدول table2 بدون أي مشاكل.
الإستعلام
الإستعلام التالي هو ما يجب كتابته بالضبط للحصول على الإحصاء المطلوب.
INSERT INTO table2(username, gender, country, salary) -- table2 هنا قمنا بتحديد أنه سيتم وضع البيانات المنسوخة في أعمدة محددة في الجدول
SELECT username, gender, country, salary FROM table1; -- table1 هنا قمنا بتحديد أنه سيتم نسخ بيانات أعمدة محددة من الجدول
SELECT * FROM table2; -- table2 هنا قمنا بعرض كل البيانات التي أصبح يحتويها الجدول
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
لاحظ أن الجدول table2 تم إضافة بيانات الجدول table1 فيه من جديد و لكن هذه المرة تم إعطاء رقم تعرفة id مختلف لكل سطر بشكل تلقائي.
| id | user | gender | country | salary |
|---|---|---|---|---|
| 1 | rami | male | Lebanon | 700.00 |
| 2 | ahmad | male | Syria | 800.00 |
| 3 | hanan | female | KSA | 750.00 |
| 4 | saly | female | Lebanon | 650.00 |
| 5 | samir | male | Egypt | 600.00 |
| 6 | rami | male | Lebanon | 700.00 |
| 7 | ahmad | male | Syria | 800.00 |
| 8 | hanan | female | KSA | 750.00 |
| 9 | saly | female | Lebanon | 650.00 |
| 10 | samir | male | Egypt | 600.00 |
المثال الثالث
الإستعلام التالي يقوم بنسخ القيم الموجودة في العامودين username و country من الجدول table1 و يضيفها في الجدول table2 و من ثم يقوم بعرض البيانات التي أصبح يحتويها الجدول table2.
الإستعلام
INSERT INTO table2(username, country) -- table2 هنا قمنا بتحديد أنه سيتم وضع البيانات المنسوخة في أعمدة محددة في الجدول
SELECT username, country FROM table1; -- table1 هنا قمنا بتحديد أنه سيتم نسخ بيانات أعمدة محددة من الجدول
SELECT * FROM table2; -- table2 هنا قمنا بعرض كل البيانات التي أصبح يحتويها الجدول
سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
لاحظ أن الجدول table2 أضيف عليه بيانات الأعمدة التي تم تحديدها فقط من الجدول table1 و الأعمدة الأخرى يظهر فيها القيمة NULL.
| id | user | gender | country | salary |
|---|---|---|---|---|
| 1 | rami | male | Lebanon | 700.00 |
| 2 | ahmad | male | Syria | 800.00 |
| 3 | hanan | female | KSA | 750.00 |
| 4 | saly | female | Lebanon | 650.00 |
| 5 | samir | male | Egypt | 600.00 |
| 6 | rami | male | Lebanon | 700.00 |
| 7 | ahmad | male | Syria | 800.00 |
| 8 | hanan | female | KSA | 750.00 |
| 9 | saly | female | Lebanon | 650.00 |
| 10 | samir | male | Egypt | 600.00 |
| 11 | rami | NULL | Lebanon | NULL |
| 12 | ahmad | NULL | Syria | NULL |
| 13 | hanan | NULL | KSA | NULL |
| 14 | saly | NULL | Lebanon | NULL |
| 15 | samir | NULL | Egypt | NULL |