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

LEFT JOIN: نگه‌داشتن همه‌ی ردیف‌های سمت چپ

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

در درس قبل دیدیم INNER JOIN دانش‌آموزی مثل «فاطمه کریمی» را که هیچ ثبت‌نامی ندارد، به‌طور کامل از نتیجه حذف می‌کند. اما گاهی دقیقاً می‌خواهیم چنین ردیف‌هایی را هم ببینیم — مثلاً برای گزارشی که «همه‌ی دانش‌آموزان» را نشان دهد، حتی آن‌هایی که هنوز ثبت‌نام نکرده‌اند. این‌جا LEFT JOIN به کار می‌آید.

ساختار پایه

sql
SELECT s.full_name, c.title
FROM students s
LEFT JOIN enrollments e ON s.id = e.student_id
LEFT JOIN courses c ON e.course_id = c.id;

LEFT JOIN همه‌ی ردیف‌های جدول سمت چپ (students، جدولی که بلافاصله بعد از FROM آمده) را نگه می‌دارد — حتی اگر هیچ تطبیقی در جدول سمت راست نداشته باشند. برای ردیف‌های بدون تطبیق، ستون‌های جدول سمت راست به‌سادگی NULL می‌شوند. بیا ببینیم:

امتحانش کن — LEFT JOIN
این‌بار «فاطمه کریمی» هم در نتیجه هست، با title برابر NULL — چون LEFT JOIN او را از جدول سمت چپ (students) نگه داشته، حتی بدون هیچ ثبت‌نامی.

یک کاربرد کلیدی: پیدا کردن ردیف‌های «بدون تطبیق»

ترکیب LEFT JOIN با شرط IS NULL روی ستون جدول سمت راست، یک الگوی فوق‌العاده رایج است: پیدا کردن دقیقاً همان ردیف‌هایی که هیچ تطبیقی ندارند.

sql
-- دانش‌آموزانی که در هیچ درسی ثبت‌نام نکرده‌اند
SELECT s.full_name
FROM students s
LEFT JOIN enrollments e ON s.id = e.student_id
WHERE e.student_id IS NULL;

بیا این الگو را امتحان کنیم:

امتحانش کن — پیدا کردن دانش‌آموزان بدون ثبت‌نام
نکته‌ی مهم: در این الگو باید حتماً روی ستونی از جدول سمت راست شرط IS NULL بگذاری (مثل e.student_id)، نه ستونی از جدول سمت چپ. اگر اشتباهی s.id IS NULL بنویسی، هیچ‌وقت نتیجه‌ای نمی‌گیری — چون id جدول students هرگز NULL نیست.

COUNT با LEFT JOIN: یک نکته‌ی ظریف

وقتی از COUNT بعد از LEFT JOIN استفاده می‌کنی، حواست باشد کدام ستون را می‌شماری. یادت هست COUNT(column) مقادیر NULL را نادیده می‌گیرد؟ همین‌جا خیلی مهم می‌شود:

sql
SELECT s.full_name, COUNT(e.course_id) AS CourseCount
FROM students s
LEFT JOIN enrollments e ON s.id = e.student_id
GROUP BY s.full_name;

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

امتحانش کن — شمارش تعداد درس‌های هر دانش‌آموز
«فاطمه کریمی» با CourseCount = 0 نمایش داده می‌شود — نه NULL و نه خطا. اگر به‌جای COUNT(e.course_id) اشتباهی از COUNT(*) استفاده می‌کردیم، برای فاطمه هم عدد ۱ می‌گرفتیم (چون LEFT JOIN برایش یک ردیف با مقادیر NULL ساخته، و COUNT(*) آن ردیف را هم می‌شمارد).

جمع‌بندی این درس

  • LEFT JOIN همه‌ی ردیف‌های جدول سمت چپ را نگه می‌دارد، حتی بدون تطبیق در سمت راست.
  • ردیف‌های بدون تطبیق، مقادیر NULL برای ستون‌های سمت راست می‌گیرند.
  • LEFT JOIN ... WHERE right.col IS NULL الگوی استاندارد پیدا کردن ردیف‌های «بدون تطبیق» است.
  • بعد از LEFT JOIN، همیشه COUNT(column) را به‌جای COUNT(*) ترجیح بده تا ردیف‌های NULL اشتباهی شمرده نشوند.

در درس بعدی سراغ RIGHT JOIN می‌رویم — همان ایده، از جهت مخالف.