LEFT JOIN و ردیف‌های بی‌جفت

با LEFT JOIN همه‌ی ردیف‌های یک جدول را نگه داری، بی‌جفت‌ها را پیدا کنی و تفاوت شرط در ON و WHERE را بدانی.

15 دقیقه مطالعه · 5 سؤال تمرینی · SQL از صفر: پرس‌وجو برای تحلیل داده

LEFT JOIN: چپی‌ها را هیچ‌وقت از دست نده

گاهی سؤال برعکس است: «همه‌ی مشتری‌ها را بده، حتی آن‌ها که سفارش ندارند.» LEFT JOIN همه‌ی ردیف‌های جدول چپ (اولی) را نگه می‌دارد. اگر جفتی در جدول راست نباشد، ستون‌های راست NULL می‌شوند:

SELECT c.name, o.id AS order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;

| name | order_id | |---|---| | Sara | 101 | | ... | ... | | Reza | NULL | | Pouya | NULL |

از همین NULL برای پیدا کردن بی‌جفت‌ها استفاده می‌کنیم (الگوی «anti-join»): مشتری‌هایی که هیچ سفارشی ندارند:

SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

دو تله‌ی LEFT JOIN

تله‌ی ۱: شمارش. بعد از LEFT JOIN، ردیف مشتری بی‌سفارش با NULL هنوز یک ردیف است. پس:

SELECT c.name, COUNT(*) AS wrong, COUNT(o.id) AS right
FROM customers c LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;

برای Pouya، COUNT(*) برابر ۱ است (خود ردیف) ولی COUNT(o.id) برابر ۰ (سفارشی نیست). برای شمردن «تعداد سفارش» همیشه ستونی از جدول راست را بشمارید.

تله‌ی ۲: شرط روی جدول راست در WHERE. اگر بنویسید LEFT JOIN orders o ON ... WHERE o.status = 'paid'، ردیف‌های بی‌جفت (که o.status در آن‌ها NULL است) حذف می‌شوند و LEFT JOIN عملاً INNER JOIN می‌شود. اگر می‌خواهید فقط سفارش‌های paid جفت شوند ولی مشتری‌ها بمانند، شرط را به ON ببرید:

LEFT JOIN orders o ON o.customer_id = c.id AND o.status = 'paid'

تمرین‌های این درس را حل کن (رایگان)