خانه/ ارتباطات و JOINها/ SELF JOIN

SELF JOIN: وصل کردن یک جدول به خودش

مبتدی ۱۲ دقیقه مطالعه

SELF JOIN نوع جدید JOIN نیست — همان INNER JOIN یا LEFT JOIN است، فقط با یک تفاوت: هر دو طرف JOIN، یک جدولاند. این الگو دقیقاً وقتی به‌کار می‌آید که یک جدول، رابطه‌ای با خودش داشته باشد — رایج‌ترین مثال: کارمندی که مدیرش هم خودش یک کارمند دیگر در همان جدول است.

جدول جدید: employees با ستون خودارجاع

در این درس از یک جدول جدید استفاده می‌کنیم:

idfull_namemanager_id
1دکتر رضاییNULL (مدیرعامل، مدیر ندارد)
2مهندس کریمی1
3مهندس احمدی1
4خانم صادقی2

ستون manager_id یک کلید خارجی است که به همان جدول employees اشاره می‌کند — یعنی مقدارش، همان id یک کارمند دیگر در همین جدول است.

چالش: چطور نام مدیر را کنار نام کارمند نشان دهیم؟

مشکل این‌جاست: اگر بنویسی SELECT full_name, manager_id FROM employees، فقط عدد شناسه‌ی مدیر را می‌بینی، نه نامش. برای گرفتن نام مدیر، باید همین جدول را یک‌بار دیگر — با نام مستعار دیگری — به خودش JOIN بزنیم:

sql
SELECT
  e.full_name AS Employee,
  m.full_name AS Manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;

این‌جا e نقش «کارمند» را بازی می‌کند و m نقش «مدیر» — با این‌که هر دو از یک جدول employees می‌آیند. توجه کن از LEFT JOIN استفاده کردیم نه INNER JOIN، چون «دکتر رضایی» مدیری ندارد (manager_idاش NULL است) و نباید کاملاً از نتیجه حذف شود. بیا ببینیم:

امتحانش کن — نمایش هر کارمند کنار مدیرش
«دکتر رضایی» با Manager = NULL نمایش داده شده (چون مدیر ندارد)، و بقیه هرکدام کنار نام مدیر واقعی‌شان دیده می‌شوند — حتی «خانم صادقی» که مدیرش («مهندس کریمی») خودش هم زیردست «دکتر رضایی» است.

چرا نام مستعار این‌جا اجباری است

در یک SELF JOIN، نوشتن employees.full_name دوبار در یک پرس‌وجو، برای SQL Server کاملاً مبهم است — نمی‌داند منظورت کدام نمونه از جدول است. به همین دلیل، نام مستعار (e و m) در SELF JOIN صرفاً یک ترجیح سبک نیست، بلکه اجباری است.

یک کاربرد دیگر: پیدا کردن همکاران هم‌مدیر

SELF JOIN را می‌توان برای پیدا کردن کارمندانی که مدیر مشترک دارند هم استفاده کرد:

sql
SELECT a.full_name AS Person1, b.full_name AS Person2
FROM employees a
INNER JOIN employees b
  ON a.manager_id = b.manager_id
  AND a.id <> b.id;
-- a.id <> b.id لازم است، وگرنه هر کارمند با خودش هم جفت می‌شود

بیا این را هم امتحان کنیم:

امتحانش کن — پیدا کردن هم‌تیمی‌ها (مدیر مشترک)
نکته: اگر شرط a.id <> b.id را حذف کنی، هر کارمند به‌عنوان «هم‌تیمی خودش» هم در نتیجه ظاهر می‌شود — چون manager_id هر کارمند با manager_id خودش هم که طبیعتاً برابر است. حذف نکردن این شرط، یکی از رایج‌ترین اشتباهات در نوشتن SELF JOIN است.

جمع‌بندی این درس (و کل فصل ۴)

  • SELF JOIN نوع جدیدی از JOIN نیست؛ فقط یک جدول را با نام‌های مستعار متفاوت، به خودش وصل می‌کند.
  • رایج‌ترین کاربرد آن، رابطه‌های سلسله‌مراتبی مثل کارمند-مدیر است.
  • نام مستعار در SELF JOIN اجباری است، چون بدون آن SQL Server نمی‌داند کدام نمونه از جدول مدنظرت است.
  • وقتی می‌خواهی جفت‌های متفاوت پیدا کنی (نه هر ردیف با خودش)، شرط a.id <> b.id را فراموش نکن.

با این درس، فصل ۴ (ارتباطات و JOINها) — شاید مهم‌ترین فصل این دوره تا این‌جا — کامل شد! از فصل بعدی، وارد پرس‌وجوهای پیشرفته‌تر می‌شویم: زیرپرس‌وجوها، EXISTS، CTE و توابع پنجره‌ای.

تمرین‌های خودآزمایی

اول خودت جواب بده، بعد پاسخ را باز کن و مقایسه کن.

۱چه وقت به SELF JOIN نیاز داریم؟نمایش پاسخ
پاسخ

وقتی جدول به خودش ارجاع می‌دهد؛ مثلاً هر کارمند ستون manager_id دارد که به کارمند دیگری در همان جدول اشاره می‌کند.

۲چرا در SELF JOIN حتماً باید Alias بدهیم؟نمایش پاسخ
پاسخ

تا دو نمونه‌ی یک جدول از هم قابل تشخیص باشند:

FROM employees e
JOIN employees m ON m.id = e.manager_id