لماذا نحتاج JOIN؟
في قواعد البيانات العلائقية (Relational Databases)، تُوزع البيانات على عدة جداول مترابطة بدلاً من وضعها في جدول واحد ضخم. هذا التصميم يُسمى التطبيع (Normalization) ويساعد في:
- تقليل تكرار البيانات
- سهولة الصيانة والتحديث
- الحفاظ على تناسق البيانات
JOIN هي الأداة التي تُمكننا من دمج البيانات من جدولين أو أكثر في استعلام واحد بناءً على عمود مشترك بينها.
تخيل متجراً إلكترونياً: لديك جدول للعملاء وجدول للطلبات.
بدلاً من تكرار اسم العميل وعنوانه في كل طلب، نحفظ فقط customer_id في جدول الطلبات ونستخدم JOIN لعرض البيانات معاً.
الجداول المستخدمة في الأمثلة
سنستخدم جدولين بسيطين لتوضيح أنواع JOIN المختلفة:
📋 جدول employees (الموظفون)
| id | name | department_id |
|---|---|---|
| 1 | أحمد | 1 |
| 2 | سارة | 2 |
| 3 | محمد | 3 |
| 4 | فاطمة | 1 |
| 5 | علي | NULL |
⚠️ لاحظ: علي ليس له قسم (NULL)
📋 جدول departments (الأقسام)
| id | name |
|---|---|
| 1 | المبيعات |
| 2 | التقنية |
| 3 | الإدارة |
| 4 | الموارد البشرية |
⚠️ لاحظ: الموارد البشرية ليس لها موظفون
أنواع JOIN
هناك عدة أنواع من JOIN، كل نوع يُرجع نتائج مختلفة:
🔵 INNER JOIN
يُرجع فقط الصفوف المتطابقة من كلا الجدولين
🟢 LEFT JOIN
يُرجع كل صفوف الجدول الأيسر + المتطابق من الأيمن
🟡 RIGHT JOIN
يُرجع كل صفوف الجدول الأيمن + المتطابق من الأيسر
🟣 FULL OUTER JOIN
يُرجع كل الصفوف من كلا الجدولين
1. INNER JOIN (الأكثر استخداماً)
المنطقة المظللة بالأصفر = الصفوف المتطابقة فقط
INNER JOIN يُرجع فقط الصفوف التي لها تطابق في كلا الجدولين.
إذا لم يوجد تطابق، لا يظهر الصف في النتيجة.
SELECT e.name AS employee_name,
d.name AS department_name
FROM employees e
INNER JOIN departments d
ON e.department_id = d.id;
النتيجة:
| employee_name | department_name |
|---|---|
| أحمد | المبيعات |
| سارة | التقنية |
| محمد | الإدارة |
| فاطمة | المبيعات |
- علي لم يظهر لأن department_id = NULL (لا تطابق)
- الموارد البشرية لم تظهر لأنه لا يوجد موظفون فيها
e و d هي أسماء مستعارة (Aliases) للجداول.
تُستخدم لاختصار الكتابة وتوضيح مصدر كل عمود، خاصة عندما يكون لعمودين نفس الاسم.
2. LEFT JOIN (أو LEFT OUTER JOIN)
كل الجدول الأيسر + المتطابق من الأيمن
LEFT JOIN يُرجع جميع صفوف الجدول الأيسر،
وإذا لم يوجد تطابق في الجدول الأيمن، تكون القيم NULL.
SELECT e.name AS employee_name,
d.name AS department_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.id;
النتيجة:
| employee_name | department_name |
|---|---|
| أحمد | المبيعات |
| سارة | التقنية |
| محمد | الإدارة |
| فاطمة | المبيعات |
| علي | NULL |
الآن ظهر علي رغم عدم وجود قسم له! هذا مفيد عندما تريد رؤية "كل الموظفين حتى الذين بدون قسم".
3. RIGHT JOIN (أو RIGHT OUTER JOIN)
كل الجدول الأيمن + المتطابق من الأيسر
RIGHT JOIN عكس LEFT JOIN - يُرجع جميع صفوف الجدول الأيمن،
وإذا لم يوجد تطابق في الجدول الأيسر، تكون القيم NULL.
SELECT e.name AS employee_name,
d.name AS department_name
FROM employees e
RIGHT JOIN departments d
ON e.department_id = d.id;
النتيجة:
| employee_name | department_name |
|---|---|
| أحمد | المبيعات |
| فاطمة | المبيعات |
| سارة | التقنية |
| محمد | الإدارة |
| NULL | الموارد البشرية |
في الواقع، نادراً ما نستخدم RIGHT JOIN. يمكن دائماً تحويله إلى LEFT JOIN بتبديل ترتيب الجداول. معظم المبرمجين يفضلون LEFT JOIN لأنه أسهل للقراءة.
4. FULL OUTER JOIN
كل الصفوف من كلا الجدولين
FULL OUTER JOIN يجمع بين LEFT و RIGHT - يُرجع جميع الصفوف من كلا الجدولين.
-- FULL OUTER JOIN
SELECT e.name AS employee_name,
d.name AS department_name
FROM employees e
FULL OUTER JOIN departments d
ON e.department_id = d.id;
النتيجة:
| employee_name | department_name |
|---|---|
| أحمد | المبيعات |
| فاطمة | المبيعات |
| سارة | التقنية |
| محمد | الإدارة |
| علي | NULL |
| NULL | الموارد البشرية |
MySQL لا يدعم FULL OUTER JOIN مباشرة. يمكن محاكاته باستخدام UNION بين LEFT JOIN و RIGHT JOIN.
5. CROSS JOIN (الضرب الديكارتي)
CROSS JOIN يُرجع كل التركيبات الممكنة بين صفوف الجدولين.
لا يحتاج شرط ON.
SELECT e.name, d.name
FROM employees e
CROSS JOIN departments d;
-- إذا كان 5 موظفين و 4 أقسام = 20 صف
كن حذراً! CROSS JOIN على جداول كبيرة يُنتج عدداً هائلاً من الصفوف. 1000 × 1000 = مليون صف!
أمثلة عملية متقدمة
JOIN مع WHERE
-- موظفو قسم التقنية فقط
SELECT e.name, d.name AS department
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
WHERE d.name = 'التقنية';
JOIN مع ORDER BY
-- الموظفون مرتبين حسب القسم
SELECT e.name, d.name AS department
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
ORDER BY d.name, e.name;
ربط أكثر من جدولين
-- الطلبات مع أسماء العملاء والمنتجات
SELECT o.id AS order_id,
c.name AS customer,
p.name AS product,
o.quantity
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
INNER JOIN products p ON o.product_id = p.id
ORDER BY o.id;
إيجاد البيانات غير المتطابقة
-- الموظفون بدون قسم
SELECT e.name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id
WHERE d.id IS NULL;
-- الأقسام بدون موظفين
SELECT d.name
FROM departments d
LEFT JOIN employees e ON d.id = e.department_id
WHERE e.id IS NULL;
اختبر معلوماتك
📝 أسئلة سريعة
1. أي نوع JOIN يُرجع فقط الصفوف المتطابقة؟
2. إذا أردت رؤية كل الموظفين حتى الذين بدون قسم، أي نوع تستخدم؟
3. ماذا تعني كلمة ON في JOIN؟
نصائح الأداء
- استخدم
INNER JOINعندما تحتاج فقط البيانات المتطابقة - أنشئ فهارس (Indexes) على أعمدة الربط
- تجنب
SELECT *- اختر الأعمدة المطلوبة فقط - استخدم Aliases للوضوح وتقليل الأخطاء
- ضع الجدول الأصغر على اليسار في LEFT JOIN
الخلاصة
| نوع JOIN | ما يُرجعه |
|---|---|
INNER JOIN |
الصفوف المتطابقة فقط من كلا الجدولين |
LEFT JOIN |
كل الجدول الأيسر + المتطابق من الأيمن |
RIGHT JOIN |
كل الجدول الأيمن + المتطابق من الأيسر |
FULL OUTER JOIN |
كل الصفوف من كلا الجدولين |
CROSS JOIN |
كل التركيبات الممكنة (الضرب الديكارتي) |