شرح SQL LEFT JOIN: الصياغة الصحيحة مع أمثلة عملية
ما هو LEFT JOIN في SQL؟
في قواعد البيانات العلائقية، غالباً ما تكون الجداول مترابطة بطريقة تسمح بتخزين المعلومة مرة واحدة فقط داخل قاعدة البيانات. هذا الأسلوب يقلل التكرار، ويحسن تنظيم البيانات، ويسهّل إدارتها على المدى الطويل. لكن عند تحليل البيانات أو استخراج تقارير منها، نحتاج عادةً إلى دمج معلومات قادمة من أكثر من جدول.
هنا يأتي دور جمل الربط في SQL، وأهمها LEFT JOIN. هذا النوع من الربط يعرض جميع الصفوف من الجدول الأول، المعروف باسم الجدول الأيسر، حتى لو لم يجد صفاً مطابقاً في الجدول الثاني. وعند غياب التطابق، تظهر القيم غير المتوفرة على شكل NULL.
صياغة LEFT JOIN الصحيحة
يمكن استخدام LEFT JOIN داخل استعلام SELECT بالشكل التالي:
SELECT columns
FROM table_1
LEFT OUTER JOIN table_2 ON relation;
والصياغة المختصرة الأكثر شيوعاً هي:
SELECT columns
FROM table_1
LEFT JOIN table_2 ON relation;
الفرق بين LEFT OUTER JOIN وLEFT JOIN شكلي فقط، والنتيجة واحدة في أغلب أنظمة قواعد البيانات.
تفكيك مكونات الاستعلام
SELECT columns: تحديد الأعمدة التي تريد عرضها في النتيجة النهائية.FROM table_1: تحديد الجدول الأساسي أو الجدول الأيسر.LEFT JOIN table_2: تحديد الجدول الثاني الذي سيتم الربط معه.ON relation: تحديد شرط المطابقة بين الجدولين.
إذا كان هناك أعمدة متشابهة الأسماء في الجدولين، فمن الأفضل كتابة اسم الجدول قبل اسم العمود مثل table_1.column_1 وtable_2.column_1 لتجنب الالتباس.
متى تستخدم LEFT JOIN؟
يُستخدم LEFT JOIN عندما تريد الحفاظ على جميع بيانات الجدول الأول، سواء وُجد لها تطابق في الجدول الثاني أم لا. وهذا مفيد جداً في حالات مثل:
- عرض جميع العملاء حتى إن لم تكن لديهم طلبات.
- إظهار جميع المنتجات حتى إن لم تُبع بعد.
- تحليل السجلات الناقصة أو اكتشاف البيانات غير المكتملة.
مثال عملي على SQL LEFT JOIN
لنفترض أن لديك قاعدة بيانات للكتب، وفيها جدول للكتب وجدول آخر للمؤلفين. بدلاً من تكرار كل بيانات المؤلف داخل كل صف من جدول الكتب، يتم الاحتفاظ ببيانات المؤلف في جدول مستقل، بينما يحتوي جدول الكتب فقط على اسم المؤلف.
جدول الكتب
| book_id | title | author_name | publ_year |
|---|---|---|---|
| 1 | Uno, nessuno e centomila | Luigi Pirandello | 1926 |
| 2 | Il visconte dimezzato | Italo Calvino | 1952 |
| 3 | Le tigri di Mompracem | Emilio Salgari | 1900 |
| 4 | Il giorno della civetta | Leonardo Sciascia | 1961 |
| 5 | A ciascuno il suo | Leonardo Sciascia | 1966 |
| 6 | Il fu Mattia Pascal | Luigi Pirandello | 1904 |
| 7 | I Malavoglia | Giovanni Verga | 1881 |
جدول المؤلفين
| author_id | name | year_of_birth | place_of_birth | trivia |
|---|---|---|---|---|
| 1 | Luigi Pirandello | 1867 | Agrigento | Nobel Prize in Literature in 1934 |
| 2 | Giovanni Verga | 1840 | Vizzini | was Senator of the Kingdom of Italy from 1920 to 1922 |
| 3 | Italo Svevo | 1861 | Trieste | real name was Aron Hector Schmitz |
| 4 | Cesare Pavese | 1908 | Santo Stefano Belbo | NULL |
| 5 | Giuseppe Tomasi di Lampedusa | 1896 | Palermo | was prince of Lampedusa from 1934 to 1957 |
يمكننا الآن ربط الجدولين بالاعتماد على اسم المؤلف باستخدام جدول books كجدول أيسر:
SELECT books.title AS book_title,
books.publ_year,
books.author_name,
authors.year_of_birth,
authors.place_of_birth
FROM books
LEFT JOIN authors
ON books.author_name = authors.name;
شرح هذا الاستعلام
- في جزء
SELECTنحدد الأعمدة المطلوبة في الناتج. - استخدمنا
ASلتغيير اسم العمودbooks.titleإلىbook_title. - في
FROM booksحددنا الجدول الأيسر. - في
LEFT JOIN authorsحددنا الجدول الثاني. - في
ON books.author_name = authors.nameعرفنا شرط المطابقة بين الجدولين.
الناتج المتوقع
| book_title | publ_year | author_name | year_of_birth | place_of_birth |
|---|---|---|---|---|
| Uno, nessuno e centomila | 1926 | Luigi Pirandello | 1867 | Agrigento |
| Il visconte dimezzato | 1952 | Italo Calvino | NULL | NULL |
| Le tigri di Mompracem | 1900 | Emilio Salgari | NULL | NULL |
| Il giorno della civetta | 1961 | Leonardo Sciascia | NULL | NULL |
| A ciascuno il suo | 1966 | Leonardo Sciascia | NULL | NULL |
| Il fu Mattia Pascal | 1904 | Luigi Pirandello | 1867 | Agrigento |
| I Malavoglia | 1881 | Giovanni Verga | 1840 | Vizzini |
لاحظ أن المؤلفين غير الموجودين في جدول authors ظهرت بياناتهم الناقصة على شكل NULL. كما أن المؤلفين الموجودين في جدول authors فقط، من دون أي كتب في جدول books، لم يظهروا هنا لأن الاستعلام حافظ على جميع صفوف الجدول الأيسر فقط.
مثال أكثر تقدماً: حساب عدد الكتب لكل مؤلف
يمكن استخدام LEFT JOIN مع دوال التجميع لإجراء تحليلات عملية على البيانات. على سبيل المثال، إذا أردت معرفة عدد الكتب المرتبطة بكل مؤلف، فيمكنك كتابة الاستعلام التالي:
SELECT authors.name AS author_name,
SUM(CASE WHEN books.title LIKE '%' THEN 1 ELSE 0 END) AS number_of_books
FROM authors
LEFT JOIN books
ON books.author_name = authors.name
GROUP BY authors.name
ORDER BY number_of_books DESC;
كيف يعمل هذا الاستعلام؟
SELECT: يحدد الأعمدة الظاهرة في النتيجة.SUM(): دالة تجميع لحساب إجمالي القيم.CASE WHEN: تُرجع1إذا كان هناك عنوان كتاب، وإلا تُرجع0.LIKE '%': تُستخدم هنا للتحقق من وجود نص داخل الحقل.GROUP BY authors.name: تجمع الصفوف المتشابهة حسب اسم المؤلف.ORDER BY number_of_books DESC: ترتب النتائج تنازلياً من الأكبر إلى الأصغر.
الناتج قبل تحديث جدول المؤلفين
| author_name | number_of_books |
|---|---|
| Luigi Pirandello | 2 |
| Giovanni Verga | 1 |
| Cesare Pavese | 0 |
| Giuseppe Tomasi di Lampedusa | 0 |
| Italo Svevo | 0 |
سبب ظهور هؤلاء المؤلفين فقط هو أن الجدول الأيسر هنا هو authors، ولذلك يتم الاحتفاظ بجميع صفوفه، حتى لو لم يكن للمؤلف أي كتاب. أما المؤلفون الموجودون في جدول books فقط، فلن يظهروا في الناتج ما لم يكونوا موجودين أيضاً في جدول authors.
ماذا يحدث بعد تحديث جدول authors؟
إذا جرى تحديث جدول authors ليشمل جميع المؤلفين المذكورين في جدول books، فستصبح النتائج أكثر اكتمالاً. لنفترض أن الجدول أصبح كالتالي:
| author_id | name | year_of_birth | place_of_birth | trivia |
|---|---|---|---|---|
| 1 | Luigi Pirandello | 1867 | Agrigento | Nobel Prize in Literature in 1934 |
| 2 | Giovanni Verga | 1840 | Vizzini | was Senator of the Kingdom of Italy from 1920 to 1922 |
| 3 | Italo Svevo | 1861 | Trieste | real name was Aron Hector Schmitz |
| 4 | Cesare Pavese | 1908 | Santo Stefano Belbo | NULL |
| 5 | Giuseppe Tomasi di Lampedusa | 1896 | Palermo | was prince of Lampedusa from 1934 to 1957 |
| 6 | Italo Calvino | 1923 | Santiago de las Vegas | NULL |
| 7 | Emilio Salgari | 1862 | Verona | NULL |
| 8 | Leonardo Sciascia | 1921 | Racalmuto | NULL |
عندها سيُظهر الاستعلام عدد الكتب لكل المؤلفين الموجودين في القاعدة:
| author_name | number_of_books |
|---|---|
| Leonardo Sciascia | 2 |
| Luigi Pirandello | 2 |
| Emilio Salgari | 1 |
| Giovanni Verga | 1 |
| Cesare Pavese | 0 |
| Giuseppe Tomasi di Lampedusa | 0 |
| Italo Svevo | 0 |
أفضل الممارسات عند استخدام LEFT JOIN
- اختر الجدول الأيسر بعناية، لأن جميع صفوفه ستظهر في النتيجة.
- استخدم أسماء الجداول قبل الأعمدة عند وجود تشابه في الأسماء.
- انتبه إلى القيم
NULLلأنها تشير غالباً إلى غياب التطابق. - ادمج
LEFT JOINمعGROUP BYوSUM()وCOUNT()للحصول على تحليلات أعمق. - احرص على أن يكون شرط
ONصحيحاً، لأن أي خطأ فيه قد يؤدي إلى نتائج مضللة.
الخلاصة التقنية
يُعد LEFT JOIN من أهم أدوات الاستعلام في SQL لأنه يسمح بدمج البيانات مع الحفاظ على جميع سجلات الجدول الأساسي. هذه الميزة تجعله مثالياً في التقارير، وتحليل العلاقات الناقصة، واكتشاف الفجوات في البيانات. إذا كنت تعمل على قواعد بيانات علائقية، فإن إتقان LEFT JOIN ليس مجرد مهارة مفيدة، بل خطوة أساسية لفهم بنية البيانات واستخراج قيمة حقيقية منها.