القائمة الرئيسية

الصفحات

الدرس 18 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);
      

بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدولين countries و users بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.


الجدول التالي يظهر البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول 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 هنا ستفهم قاعدة البيانات أنك تقصد العامود
    


ذكر أسماء الجداول و أسماء الأعمدة التي تربط الجداول ببعضها

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

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

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

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

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

  • وضع الكلمة ON في النهاية لتحديد أسماء الأعمدة التي تربط الجدولين ببعض.

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

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

قاعدة عامة

لجلب الأسطر التي تحتوي قيم مشتركة نضع بين الجداول الكلمة 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 هنا حددنا أن قيم العامود
      

الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.


سنحصل على النتيجة التالية عند تنفيذ الإستعلام.
لاحظ أن كل مستخدم لا يملك 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

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

لجلب كل قيم الجدول الأيسر بالإضافة إلى القيم المشتركة معه من الجدول الأيمن, نضع بين الجداول LEFT OUTER JOIN أو 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 هنا حددنا أن قيم العامود
      

الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.


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

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 فقط.
الفكرة هنا هي أنه في حال كانت القيم التي ننوي إحضارها من الجداول الأيسر غير موجودة في الجدول الأيمن فإننا أيضاً نريد وضعها كالتالي.


مثال

الإستعلام التالي, يقوم بطباعة 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 هنا حددنا أن قيم العامود
      

الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.


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

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 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;
    

مثال

الإستعلام التالي, يقوم بجلب معلومات المستخدم سواء كانت مرتبطة بالجدول 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
      

الفيديو التالي يشرح كود الإستعلام بدقة و يشرح كيف حصلنا على النتيجة.


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

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

الكلمة AS مع الجداول

في الدروس السابقة شاهدنا أنه بإمكاننا تغيير أسماء الجداول عند جلبها بواسطة الكلمة AS.

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


الشكل العام لإستخدامها مع الجداول

      SELECT alias_name.column1, alias_name.column2, ...
      FROM table_name AS alias_name;
    

إذاً لوضع إسم مختصر للجدول, نضع AS بعد إسم الجدول و من ثم ندخل الإسم المختصر له.
بعد وضع إسم مختصر للجدول, تستخدم هذا الإسم نفسه للوصول لأعمدته.

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

قم بتنفيذ الإستعلام التالي حتى تنشئ قاعدة بيانات جديدة إسمها 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);
      

بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدولين countries و users بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.


الجدول التالي يظهر البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول 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.

متى نحتاج وضع أسماء مختصرة؟


الحالة الأولى

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

فمثلاً, إذا كنا نريد طباعة first_name و last_name المستخدمين الموضوعين في الجدول users.
لاحظ كيف سكون شكل الإستعلام, إذا قمنا بذكر إسم الجدول الذي يحتوي على الأعمدة أو إذا وضعنا إسم مختصر للجدول.

الإستعلام

شكل الإستعلام بدون وضع أسماء مختصرة للجداول.

        SELECT first_name, last_name
        FROM users;
      

شكل الإستعلام مع ذكر إسم الجدول الذي نتعامل مع أعمدته.

        SELECT users.first_name, users.last_name
        FROM users;
      

شكل الإستعلام إذا وضعنا إسم مختصر للجدول users مثل الحرف u فقط.

        SELECT u.first_name, u.last_name
        FROM users AS u;
      

سنحصل على النتيجة التالية عند تنفيذ الإستعلام.

first_name last_name
Rami Masri
Ahmad Naji
Hanan Mostafa
Saly Harmush
Samir Saleh
Hamad Akel
Abdullah Helmi
Rashed Masri
Majed Alali
Rayan Kasabi


الحالة الثانية

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

الآن, في حال أردنا طباعة id و username و country كل مستخدم موجود في الجدول users سواء كان يملك رقم بلد محدد أم لا يمكننا أن نربط الجدولين بطريقة LEFT JOIN تماماَ كما فعلنا في الدرس السابق.
هنا ستلاحظ أن حجم الكود سيصبح أقل إذا وضعنا أسماء مختصرة للجداول.
و لك أن تتخيل كم سيصبح حجم الكود أصغر إذا كنا سنحضر المعلومات من أعمدة أخرى و كنا ننوي نضع شروط.

الإستعلام

شكل الإستعلام مع ذكر إسم الجدول الذي نتعامل مع أعمدته.

        SELECT users.id, users.username, countries.name AS country
        FROM users LEFT JOIN countries
        ON users.country_id = countries.id;
      

شكل الإستعلام إذا وضعنا الحرف u كإسم مختصر للجدول users و الحرف c كإسم مختصر للجدول countries.

        SELECT u.id, u.username, c.name AS country
        FROM users AS u LEFT JOIN countries AS c
        ON u.country_id = c.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


الحالة الثالثة

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

ربط بيانات الجدول نفسه ببعضها ( Self Join ) لم نتطرق له سابقاً لأنك يجب أن تعرف كيف تضع إسم مختصر للجدول حتى تتمكن من فعل ذلك.
في الدرس التالي ستتعلم كيف يتم ربط بيانات الجدول نفسه ببعضها بتفصيل ممل.

في حال كان الجدول نفسه يحتوي على أعمدة قيمها مترابطة ببعضها البعض و تريد إسترجاعها بشكل مرتب, هنا يجب أن تربط الأعمدة مع بعضها بأسلوب يقال له الربط الذاتي ( Self Join ) لأننا نتعامل مع أعمدة موجودة في نفس الجدول.


حالات نطبق فيها الربط الذاتي

في مواقع التواصل الإجتماعي مثل فيسبوك يمكنك وضع تعليق ( Comment ) على أي منشور ( Post ) تراه و بعدها يمكن لشخص أخر أن يضع تعليق آخر كردّ على تعليقك أنت. إذاً هنا عندنا ربط ذاتي لأن التعليق الجديد مرتبط بالتعليق الأول و كلاهما موضوع في نفس الجدول.

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

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

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

الإستعلام

        -- سيتم حذفها harmash في حال كان يوجد بالأساس قاعدة بيانات إسمها
        DROP DATABASE IF EXISTS harmash;

        -- harmash هنا قمنا بإنشاء قاعدة بيانات جديدة إسمها
        CREATE DATABASE harmash;

        -- harmash هنا قمنا بتحديد أن أي إستعلام جديد سيتم تنفيذه على قاعدة البيانات
        USE harmash;

        -- يتألف من 5 أعمدة users هنا قمنا بإنشاء جدول جديد إسمه
        -- لأننا قمنا بتحديدها قبل إستدعاء هذا الأمر harmash سيتم إنشاء هذا الجدول بداخل قاعدة البيانات
        CREATE TABLE employees (
        id         INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
        name       VARCHAR(50),
        manager_id INT
        );

        -- هنا قمنا بإضافة 10 أسطر في الجدول, أي أضفنا معلومات 10 مستخدمين
        -- لاحظ أننا لم نحدد أسماء الأعمدة التي سنضع فيها البيانات لأننا قمنا بملئ جميع المعلومات
        -- في البداية هو حتى يكون عدد القيم الموضوعة يساوي عدد أعمدة الجدول null سبب وضع الكلمة
        -- ستقوم قاعدة البيانات بوضع رقم تعرفة مختلف لكل سطر null مكان الكلمة
        INSERT INTO employees VALUES (null, "Rami", null);
        INSERT INTO employees VALUES (null, "Ahmad", 1);
        INSERT INTO employees VALUES (null, "Hanan", 1);
        INSERT INTO employees VALUES (null, "Saly", 1);
        INSERT INTO employees VALUES (null, "Samir", 1);
      

بعد تنفيذ الإستعلام السابق في phpMyAdmin سيتم إنشاء قاعدة البيانات harmash و إنشاء الجدول employees بداخلها.
قم بالنقر على إسم قاعدة البيانات harmash من القائمة اليسرى حتى تبدأ بالتعامل معها و تطبيق ما ستتعلمه في هذا الدرس.


البيانات التي قمنا بإضافتها بشكل إفتراضي في الجدول employees.

id name manager_id
1 Rami NULL
2 Ahmad 1
3 Hanan 1
4 Saly 1
5 Samir 1

نلاحظ أن جدول الموظفين يتضمن عامودين متشابهين هما id و manager_id و فكرتهما هي التالية:

  • العامود id يحتوي على رقم تعرفة كل موظف.

  • العامود manager_id يحتوي على رقم تعرفة الموظف الذي يعتبر المدير بالنسبة للموظف.


قراءة بيانات الموظفين

  • الموظف Rami, لا يوجد عنده manager_id و هذا يعني أنه هو المدير.
        بالمنطق إذا كنت موظف في شركة و لا يوجد مدير مسؤول عنك, فهذا يعني أنك أنت نفسك مدير الشركة.

  • الموظف Ahmad, مديره هو الموظف الذي يملك رقم id يساوي 1, أي الموظف Rami هو مديره.

  • الموظفة Hanan, مديرها هو الموظف الذي يملك رقم id يساوي 1, أي الموظف Rami هو مديره.

  • الموظفة Saly, مديرها هو الموظف الذي يملك رقم id يساوي 1, أي الموظف Rami هو مديره.

  • الموظف Samir, مديره هو الموظف الذي يملك رقم id يساوي 1, أي الموظف Rami هو مديره.

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

في البداية عند ربط قيم الجداول عند جلبها, سبق و عرفنا أنه يوجد 4 أشكال أساسية لربط قيمهم كما في الصورة التالية.


الآن لربط قيم الجدول نفسه ببعضها عند جلبها, نقوم بجلب قيم الجدول نفسه مرتين و من ثم نربطهما ببعضهما كأنهما جدولين منفصلين عن بعضهما بالضبط كما كنا نربط الجداول مع بعضها.

حتى تتمكن من جلب قيم الجدول نفسه مرتين, يجب أن تذكر إسم الجدول مرتين و تعطيه إسمين مختلفين. عندها يمكنك أن تتعامل معه و كأنه جدولين منفصلين.
في مثالنا الحالي, النسخة الأولى من الجدول employees سنقوم بتسميتها e1, و النسخة الثانية سنقوم بتسميتها e2.

أمثلة حول ربط معلومات الجدول نفسه ببعضها عند جلبها


المثال الأول

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

ما فعلناه لربط القيم المشتركة في الجدول نفسه ببعضها هو إعطاء الجدول إسمين مختلفين هما e1 و e2 مع وضع الكلمة JOIN بينهما.
الصورة التالية توضح كيف سيتم ربط قيم الجدولين.

إذاً سيتم جلب قيم العامودين id و name من الجدول e1, و قيم العامود name من الجدول e2.


الإستعلام

        SELECT                                      -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عامود من أي جدول سيتم جلبه
        e1.id AS 'Employee Id',                 -- الموظف فيه id لأننا سنعرض Employee Id هذا العامود قمنا بتسميته
        e1.name AS Employee,                    -- لأننا سنعرض إسم الموظف فيه Employee هذا العامود قمنا بتسميته
        e2.name AS Manager                      -- لأننا سنعرض إسم الموظف الذي يعتبر بمثابة مدير للموظف Manager هذا العامود قمنا بتسميته
        FROM
        employees AS e1 JOIN employees AS e2    -- مع القيم المشتركة بينهما فقط e2 و في جدول آخر إسمه e1 في جدول إسمه employees هنا قمنا بتحديد أننا نريد كل قيم الجدول
        ON
        e1.manager_id = e2.id;                  -- e2 الموجودة في الجدول id هي قيم العامود e1 الموجودة في الجدول manager_id هنا حددنا أن قيم العامود
      

سنحصل على النتيجة التالية عند تنفيذ الإستعلام.

Employee ID Employee Manager
2 Ahmad Rami
3 Hanan Rami
4 Saly Rami
5 Samir Rami


المثال الثاني

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

ما فعلناه لربط كل القيم الموجودة في الجدول نفسه ببعضها هو إعطاء الجدول إسمين مختلفين هما e1 و e2 مع وضع الكلمة LEFT JOIN بينهما.
الصورة التالية توضح كيف سيتم ربط قيم الجدولين.

إذاً سيتم جلب قيم العامودين id و name من الجدول e1, و قيم العامود name من الجدول e2.


الإستعلام

        SELECT                                           -- هنا قمنا بتحديد الأعمدة التي نريد الحصول علي قيمها مع تحديد كل عامود من أي جدول سيتم جلبه
        e1.id AS 'Employee Id',                      -- الموظف فيه id لأننا سنعرض Employee Id هذا العامود قمنا بتسميته
        e1.name AS Employee,                         -- لأننا سنعرض إسم الموظف فيه Employee هذا العامود قمنا بتسميته
        e2.name AS Manager                           -- لأننا سنعرض إسم الموظف الذي يعتبر بمثابة مدير للموظف Manager هذا العامود قمنا بتسميته
        FROM
        employees AS e1 LEFT JOIN employees AS e2    -- e2 و القيم المشتركة معها فقط من e1 مع كل قيم  e2 و في جدول آخر إسمه e1 في جدول إسمه employees هنا قمنا بتحديد أننا نريد كل قيم الجدول
        ON
        e1.manager_id = e2.id;                       -- e2 الموجودة في الجدول id هي قيم العامود e1 الموجودة في الجدول manager_id هنا حددنا أن قيم العامود
      

سنحصل على النتيجة التالية عند تنفيذ الإستعلام.

Employee ID Employee Manager
1 Rami NULL
2 Ahmad Rami
3 Hanan Rami
4 Saly Rami
5 Samir Rami


المثال الثالث

الإستعلام التالي هو نفس الإستعلام الموضوع في المثال الثاني تماماً مع فرق واحد و هو أنه في حال كان الموظف لا يوجد عنده مدير - أي الحقل Manager عنده يساوي NULL - سيتم تبديل قيمته بعبارة 'No Manager'.


الإستعلام

        SELECT
        e1.id AS 'Employee Id',
        e1.name AS Employee,
        IFNULL(e2.name, 'No Manager') AS Manager     -- 'No Manager' فارغاً سيتم تبديله بعبارة Manager في حال كان الحقل الموضوع في العامود
        FROM
        employees AS e1 LEFT JOIN employees AS e2
        ON
        e1.manager_id = e2.id;
      

سنحصل على النتيجة التالية عند تنفيذ الإستعلام.

Employee ID Employee Manager
1 Rami No Manager
2 Ahmad Rami
3 Hanan Rami
4 Saly Rami
5 Samir Rami