Programming Basics SQL HTML CSS JavaScript Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Learn Typing

SQLطرق ربط المعلومات عند جلبها

  • مفهوم ربط المعلومات عند جلبها
  • طرق ربط القيم التي يتم جلبها من عدة جداول
  • تجهيز قاعدة البيانات التي سنطبق عليها
  • كيف يتم ربط قيم الجداول في الإستعلام
  • جلب القيم المشتركة بين الجداول
  • جلب كل قيم الجدول الأيسر بالإضافة إلى القيم المشتركة معه من الجدول الأيمن
  • جلب كل قيم الجدول الأيمن بالإضافة إلى القيم المشتركة معه من الجدول الأيسر
  • جلب القيم المشتركة و الغير مشتركة بين الجداول

مفهوم ربط المعلومات عند جلبها

بعد تخزين البيانات في جداول متفرقة و بشكل منطقي كما شاهدنا في الدرسين السابقين، لا بد لنا من معرفة كيف سنسترجع هذه المعلومات بشكل مرتب و كأنها موضوعة في جدول واحد لأن أي معلومات سنطلبها من قاعدة البيانات سترجعها لنا في جدول واحد.

إذاً، في هذا الدرس سنتعلم طرق ربط المعلومات المخزنة في عدة جداول عند جلبها و عرضها في جدول واحد.

طرق ربط القيم التي يتم جلبها من عدة جداول

عند جلب المعلومات المخزنة في عدة جداول و في وقت واحد، يوجد 4 طرق أساسية لتحديد كيف سيتم دمج معلوماتهم التي سيتم إرجاعها كما يلي.

أنواع العلاقات في قواعد البيانات

  • إذا اخترت الدمج Inner Join فأنت بذلك تريد الحصول فقط على القيم المشتركة بين الجدولين.
  • إذا اخترت الدمج Full Join فأنت بذلك تريد الحصول على القيم المشتركة و الغير مشتركة بين الجدولين.
  • إذا اخترت الدمج Left Join فأنت بذلك تريد الحصول على كل قيم الجدول الأيسر بالإضافة إلى القيم المشتركة معه من الجدول الأيمن.
  • إذا اخترت الدمج Right Join فأنت بذلك تريد الحصول على كل قيم الجدول الأيمن بالإضافة إلى القيم المشتركة معه من الجدول الأيسر.

تجهيز قاعدة البيانات التي سنطبق عليها

قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها harmash تحتوي على الجداول التالية:

  • الجدول الأول إسمه countries و هو مخصص لحفظ معلومات البلدان.
  • الجدول الثاني إسمه users و هو مخصص لحفظ معلومات المستخدمين و التي من ضمنها بلد كل مستخدم.

مثال

-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
DROP DATABASE IF EXISTS harmash;
-- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
CREATE DATABASE harmash;
-- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
USE harmash;
-- يتألف من عامودين countries هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE countries (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
UNIQUE (name)
);
-- هنا قمنا بإضافة 5 أسطر في الجدول, أي أضفنا معلومات 5 بلدان
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة
-- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة
INSERT INTO countries VALUES (null, "KSA");
INSERT INTO countries VALUES (null, "Oman");
INSERT INTO countries VALUES (null, "Egypt");
INSERT INTO countries VALUES (null, "Kuwait");
INSERT INTO countries VALUES (null, "Bahrain");
-- يتألف من 5 أعمدة users هنا قمنا بإنشاء جدول جديد إسمه
-- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30),
first_name VARCHAR(50),
last_name VARCHAR(50),
country_id INT,
UNIQUE (username)
);
-- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 مستخدمين
-- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
-- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة
-- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة
INSERT INTO users VALUES (null, "rami", "Rami", "Masri", 1);
INSERT INTO users VALUES (null, "ahmad", "Ahmad", "Naji", 2);
INSERT INTO users VALUES (null, "hanan", "Hanan", "Mostafa", 5);
INSERT INTO users VALUES (null, "saly", "Saly", "Harmush", null);
INSERT INTO users VALUES (null, "samir", "Samir", "Saleh", 3);
INSERT INTO users VALUES (null, "hamad", "Hamad", "Akel", 2);
INSERT INTO users VALUES (null, "abdullah", "Abdullah", "Helmi", 1);
INSERT INTO users VALUES (null, "rashed", "Rashed", "Masri", 5);
INSERT INTO users VALUES (null, "majed", "Majed", "Alali", null);
INSERT INTO users VALUES (null, "rayan", "Rayan", "Kasabi", null);
-- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها DROP DATABASE IF EXISTS harmash; -- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها CREATE DATABASE harmash; -- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات USE harmash; -- يتألف من عامودين countries هنا قمنا بإنشاء جدول جديد إسمه -- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات CREATE TABLE countries ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), UNIQUE (name) ); -- هنا قمنا بإضافة 5 أسطر في الجدول, أي أضفنا معلومات 5 بلدان -- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات -- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة -- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة INSERT INTO countries VALUES (null, "KSA"); INSERT INTO countries VALUES (null, "Oman"); INSERT INTO countries VALUES (null, "Egypt"); INSERT INTO countries VALUES (null, "Kuwait"); INSERT INTO countries VALUES (null, "Bahrain"); -- يتألف من 5 أعمدة users هنا قمنا بإنشاء جدول جديد إسمه -- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات CREATE TABLE users ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, username VARCHAR(30), first_name VARCHAR(50), last_name VARCHAR(50), country_id INT, UNIQUE (username) ); -- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 مستخدمين -- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات -- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة -- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة INSERT INTO users VALUES (null, "rami", "Rami", "Masri", 1); INSERT INTO users VALUES (null, "ahmad", "Ahmad", "Naji", 2); INSERT INTO users VALUES (null, "hanan", "Hanan", "Mostafa", 5); INSERT INTO users VALUES (null, "saly", "Saly", "Harmush", null); INSERT INTO users VALUES (null, "samir", "Samir", "Saleh", 3); INSERT INTO users VALUES (null, "hamad", "Hamad", "Akel", 2); INSERT INTO users VALUES (null, "abdullah", "Abdullah", "Helmi", 1); INSERT INTO users VALUES (null, "rashed", "Rashed", "Masri", 5); INSERT INTO users VALUES (null, "majed", "Majed", "Alali", null); INSERT INTO users VALUES (null, "rayan", "Rayan", "Kasabi", null);

فيما يلي البيانات التي قمنا بإضافتها في الجدول countries.

countries
id name
1 KSA
2 Oman
3 Egypt
4 Kuwait
5 Bahrain

فيما يلي البيانات التي قمنا بإضافتها في الجدول users.

users
id username first_name last_name country_id
1 rami Rami Masri 1
2 ahmad Ahmad Naji 2
3 hanan Hanan Mostafa 5
4 saly Saly Harmush NULL
5 samir Samir Saleh 3
6 hamad Hamad Akel 2
7 abdullah Abdullah Helmi 1
8 rashed Rashed Masri 5
9 majed Majed Alali NULL
10 rayan Rayan Kasabi NULL

تحليل علاقة الجداول

إذا وضعنا الجدولين بجانب بعض، سنلاحظ كيف ربطنا قيم الجدول users بقيم الجدول countries من خلال رقم التعرفة id الخاص بكل بلد.

تحليل علاقة جداول قواعد البيانات

ملاحظات حول الجدول users

  • عند تحديد بلدان المستخدمين لم نقم بكتابة أسماء البلدان من جديد، بل وضعنا فقط رقم id البلد المذكور في الجدول countries.
  • يوجد 3 مستخدمين لم يتم تحديد بلدهم، أي عندهم قيمة الحقل country_id تساوي NULL.
  • لا يوجد أي مستخدم من البلد الذي يملك رقم id يساوي 4، أي لا يوجد أي مستخدم من Kuwait.

كيف يتم ربط قيم الجداول في الإستعلام

عند جلب البيانات من أكثر من جدول, يجب تحديد إسم الجدول الذي يحتوي على العمود لتضمن أن لا يحدث تضارب في الأسماء.
فعلى سبيل المثال، في كل من الجدولين users و countries يوجد عمود إسمه id.

إذا كنت سنحضر البيانات من هذين الجدولين في نفس الوقت فإنك حتماً ستواجه مشكلة تضارب الأسماء عند محاولة عرض قيم العمود id لأن قاعدة البيانات لن تعرف أي id بالضبط أنت تريد.

كل ما عليك فعله لتجنب حدوث تضارب في الأسماء هو ذكر إسم الجدول الذي تريد إحضار قيم العمود منه قبله كما يلي.

users.id -- users الموجود في الجدول id هنا ستفهم قاعدة البيانات أنك تقصد العامود
countries.id -- countries الموجود في الجدول id هنا ستفهم قاعدة البيانات أنك تقصد العامود
users.id -- users الموجود في الجدول id هنا ستفهم قاعدة البيانات أنك تقصد العامود countries.id -- countries الموجود في الجدول id هنا ستفهم قاعدة البيانات أنك تقصد العامود

نقطة أخرى عليك الإنتباه لها و هي أنك حتى لو ذكرت إسم كل جدول ستحضر قيم أعمدته، فإنك لا تزال مجبر على ذكر إسم كل جدول بعد الكلمة FROM. بالإضافة إلى ذلك، يجب أن تحدد إسم العمود الذي يربط الجدولين ببعضهما في نهاية الإستعلام بعد الكلمة ON كما يلي.

SElECT columuns
FROM table1 join_type table2
ON table1.table2_id = table_2.id
SElECT columuns FROM table1 join_type table2 ON table1.table2_id = table_2.id

خلاصة

في حال كنت ستحضر قيم من الجدولين users و countries في نفس الإستعلام، فيجب أن تفعل التالي:

  • ذكر إسم الجدولين users و countries بعد الكلمة FROM لأنك يجب أن تذكر من أين ستحضر قيم الجداول.
  • وضع كلمة بين إسم الجدولين تحدد من خلالها كيف تريد أن يتم ربط قيمهما.
  • وضع الكلمة ON في النهاية لتحديد أسماء الأعمدة التي تربط الجدولين ببعض.

جلب القيم المشتركة بين الجداول

نقصد بالقيم المشتركة بين الجداول، هو عندما يكون الجدول يشير إلى معلومة موجودة في جدول آخر. عندها تكون المعلومة مشتركة بينهما.
الصورة التالية توضح القيم المشتركة بين الجدولين users و countries.

SQL INNER JOIN


لجلب الأسطر التي تحتوي قيم مشتركة نضع بين الجداول الكلمة INNER JOIN و التي يمكنك اختصارها بالكلمة JOIN فقط.
لتحديد ما هو الحقل المشترك بين الجداول و الذي يربطهم مع بعض, نستخدم الكلمة ON.


الإستعلام التالي يقوم بطباعة id و username و country كل مستخدم بشرط ان يكون المستخدم يملك رقم بلد موجود في الجدول countries.

مثال

SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه
FROM users JOIN countries -- هنا قمنا بتحديد أسماء الجداول التي سنحضر القيم منها بالإضافة إلى تحديد أننا نريد القيم المشتركة بينهما فقط
ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود
SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه FROM users JOIN countries -- هنا قمنا بتحديد أسماء الجداول التي سنحضر القيم منها بالإضافة إلى تحديد أننا نريد القيم المشتركة بينهما فقط ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود

النتيجة

id username country
1 rami KSA
2 ahmad Oman
3 hanan Bahrain
5 samir Egypt
6 hamad Oman
7 abdullah KSA
8 rashed Bahrain

لاحظ أن كل مستخدم لا يملك country_id لم يتم وضعه في النتيجة.
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.

جلب كل قيم الجدول الأيسر بالإضافة إلى القيم المشتركة معه من الجدول الأيمن

لجلب كل قيم الجدول الأيسر بالإضافة إلى القيم المشتركة معه من الجدول الأيمن نضع بين الجداول LEFT OUTER JOIN أو LEFT JOIN.
الفكرة هنا هي أنه في حال كانت القيم التي ننوي إحضارها من الجداول الأيسر غير موجودة في الجدول الأيمن فإننا أيضاً نريد وضعها كما يلي.

SQL LEFT JOIN


الإستعلام التالي يقوم بطباعة id و username و country كل مستخدم موجود في الجدول users سواء كان يملك رقم بلد محدد أم لا لأننا وضعنا الجدول users من الناحية اليسرى و حددنا أننا نريد ربط الجدولين بطريقة LEFT JOIN.

إذاً في حال كان المستخدم يملك رقم بلد محدد سيتم إستبداله بإسم بلده، و في حال لم يكن يملك رقم بلد سيتم وضع القيمة الموجودة أصلاً في العمود.

مثال

SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه
FROM users LEFT JOIN countries -- countries و القيم المشتركة معها فقط في الجدول users هنا قمنا بتحديد أننا نريد كل قيم الجدول
ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود
SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه FROM users LEFT JOIN countries -- countries و القيم المشتركة معها فقط في الجدول users هنا قمنا بتحديد أننا نريد كل قيم الجدول ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود

النتيجة

id username country
1 rami KSA
2 ahmad Oman
3 hanan Bahrain
4 saly NULL
5 samir Egypt
6 hamad Oman
7 abdullah KSA
8 rashed Bahrain
9 majed NULL
10 rayan NULL

لاحظ أنه تم وضع جميع المستخدمين و من كان يملك منهم رقم بلد تم ذكر إسم بلده.
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.

جلب كل قيم الجدول الأيمن بالإضافة إلى القيم المشتركة معه من الجدول الأيسر

لجلب كل قيم الجدول الأيمن بالإضافة إلى القيم المشتركة معه من الجدول الأيسر نضع بين الجداول RIGHT OUTER JOIN أو RIGHT JOIN.
الفكرة هنا هي أنه في حال كانت القيم التي ننوي إحضارها من الجداول الأيسر غير موجودة في الجدول الأيمن فإننا أيضاً نريد وضعها كما يلي.

SQL RIGHT JOIN


الإستعلام التالي يقوم بطباعة id و username و country كل مستخدم بشرط أن يكون يملك رقم بلد موجود في الجدول countries. كما أنه سيتم ذكر أسماء كل البلدان الموجودة في الجدول countries سواء كان هناك مستخدمين من هذا البلد أم لم يكن لأننا وضعنا الجدول countries من الناحية اليمنى و حددنا أننا نريد ربط الجدولين بطريقة RIGHT JOIN.

إذاً في حال كان المستخدم يملك رقم بلد محدد سيتم إستبداله بإسم بلده، و في حال كان رقم البلد غير محدد من قبل أي مستخدم فإنه أيضاً سيتم عرضه.

مثال

SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه
FROM users RIGHT JOIN countries -- countries و القيم المشتركة معها فقط في الجدول users هنا قمنا بتحديد أننا نريد كل قيم الجدول
ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود
SELECT users.id, users.username, countries.name AS 'country' -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عمود من أي جدول سيتم جلبه FROM users RIGHT JOIN countries -- countries و القيم المشتركة معها فقط في الجدول users هنا قمنا بتحديد أننا نريد كل قيم الجدول ON users.country_id = countries.id; -- countries الموجودة في الجدول id هي قيم العمود users الموجودة في الجدول country_id هنا حددنا أن قيم العامود

النتيجة

id username country
1 rami KSA
2 ahmad Oman
3 hanan Bahrain
5 samir Egypt
6 hamad Oman
7 abdullah KSA
8 rashed Bahrain
NULL NULL Kuwait

لاحظ أنه تم وضع جميع البلدان سواء كان هناك مستخدمين منها أم لم يكن و تم وضع أسماء بلدان المستخدمين.
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.

جلب القيم المشتركة و الغير مشتركة بين الجداول

نقصد بالقيم المشتركة و الغير مشتركة هي أنه يجب إحضار كل المعلومات الموجودة في الجداول مع ربط القيم المشتركة بينهما.
الصورة التالية توضح القيم المشتركة و الغير مشتركة بين الجدولين users و countries.

SQL FULL JOIN


جلب الأسطر التي تحتوي قيم مشتركة و غير مشتركة يختلف من قاعدة بيانات لأخرى. في قواعد بيانات SQL Server يمكنك بكل سهولة وضع الكلمة FULL OUTER JOIN بين أسماء الجداول فقط و التي يمكنك اختصارها بالكلمة FULL JOIN أيضاً. و بالطبع لتحديد ما هو الحقل المشترك بين الجداول و الذي يربطهم مع بعض نستخدم الكلمة ON.


كحل عام يمكن تطبيقه في جميع قواعد البيانات بما فيها قواعد بيانات MySQL، يمكنك إحضار كل القيم الموجودة في الجدول الأيسر مع القيم المشتركة معها في الجدول الأيمن و إحضار كل القيم الموجودة في الجدول الأيمن مع القيم المشتركة معها في الجدول الأيسر و من ثم دمجها مع بعض و إزالة القيم المكررة بواسطة الأمر UNION على النحو التالي.

SELECT column_name(s)
FROM table1 LEFT JOIN table2
ON table1_column = table2_column
UNION
SELECT column_name(s)
FROM table1 RIGHT JOIN table2
ON table1_column = table2_column;
SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1_column = table2_column UNION SELECT column_name(s) FROM table1 RIGHT JOIN table2 ON table1_column = table2_column;

الإستعلام التالي يقوم بجلب معلومات المستخدم سواء كانت مرتبطة بالجدول countries أو غير مرتبطة به.
كما أنه يقوم بجلب أسماء البلدان سواء كانت مرتبطة بالجدول users أو غير مرتبطة به.

مثال

SELECT users.id, users.username, countries.name AS 'country' -- countries بالإضافة إلى القيم المشتركة معها في الجدول users هنا قمنا بإحضار كل قيم الجدول
FROM users LEFT JOIN countries
ON users.country_id = countries.id
UNION -- هنا قمنا بدمج النتيجتين السابقتين في جدول واحد مع عدم وضع أسطر تحتوي على قيم مكررة
SELECT users.id, users.username, countries.name -- users بالإضافة إلى القيم المشتركة معها في الجدول countries هنا قمنا بإحضار كل قيم الجدول
FROM users RIGHT JOIN countries
ON users.country_id = countries.id
SELECT users.id, users.username, countries.name AS 'country' -- countries بالإضافة إلى القيم المشتركة معها في الجدول users هنا قمنا بإحضار كل قيم الجدول FROM users LEFT JOIN countries ON users.country_id = countries.id UNION -- هنا قمنا بدمج النتيجتين السابقتين في جدول واحد مع عدم وضع أسطر تحتوي على قيم مكررة SELECT users.id, users.username, countries.name -- users بالإضافة إلى القيم المشتركة معها في الجدول countries هنا قمنا بإحضار كل قيم الجدول FROM users RIGHT JOIN countries ON users.country_id = countries.id

النتيجة

id username country
1 rami KSA
2 ahmad Oman
3 hanan Bahrain
4 saly NULL
5 samir Egypt
6 hamad Oman
7 abdullah KSA
8 rashed Bahrain
9 majed NULL
10 rayan NULL
NULL NULL Kuwait

لاحظ أنه تم وضع جميع المستخدمين و جميع البلدان سواء كان هناك مستخدمين منها أم لم يكن.
الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.