خانه/ پرس‌وجوهای پیشرفته/ EXISTS

EXISTS: بررسی وجود رابطه، بدون تله‌ی NULL

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

در درس قبل دیدیم NOT IN با یک NULL داخل زیرپرس‌وجو، بی‌سروصدا و بدون خطا، نتیجه‌ی کاملاً خالی می‌دهد. EXISTS دقیقاً همان سوال را می‌پرسد — «آیا رابطه‌ای وجود دارد؟» — اما با روشی که این مشکل را ندارد.

EXISTS دقیقاً چه می‌کند؟

EXISTS فقط بررسی می‌کند آیا زیرپرس‌وجو حداقل یک ردیف برمی‌گرداند یا نه — نتیجه‌اش همیشه TRUE یا FALSE است، هیچ‌وقت UNKNOWN. برخلاف IN، اصلاً به مقادیر داخل زیرپرس‌وجو کاری ندارد؛ فقط می‌پرسد چیزی پیدا شد یا نه.

sql
-- دانش‌آموزانی که حداقل در یک درس ثبت‌نام کرده‌اند
SELECT full_name
FROM students s
WHERE EXISTS (
  SELECT 1 FROM enrollments e WHERE e.student_id = s.id
);

نکته‌ی ظریف: داخل زیرپرس‌وجوی EXISTS معمولاً به‌جای نام ستون، همان SELECT 1 نوشته می‌شود — چون مقدار واقعی ستون‌ها اصلاً مهم نیست، فقط وجود ردیف مهم است. بیا امتحان کنیم:

امتحانش کن — EXISTS همبسته

NOT EXISTS — جایگزین امن NOT IN

حالا بیا دقیقاً همان پرس‌وجوی «کدام درس‌ها هیچ دانش‌آموزی ندارند؟» را از درس قبل، این‌بار با NOT EXISTS بازنویسی کنیم و کنار نسخه‌ی NOT IN بگذاریم:

sql
-- همان سوال قبلی، این‌بار امن:
SELECT title
FROM courses c
WHERE NOT EXISTS (
  SELECT 1 FROM enrollments e WHERE e.course_id = c.id
);

بیا هر دو نسخه را دقیقاً روی همان داده‌ای که در درس قبل تله‌اش را دیدیم، کنار هم اجرا کنیم:

امتحانش کن — مقایسه‌ی NOT IN (باگ‌دار) و NOT EXISTS (امن)
با NOT EXISTS، «هنر» درست پیدا می‌شود — همان داده، همان مقدار NULL در enrollments، اما بدون تله. حالا خودت خط NOT IN بالا را از کامنت خارج کن (و خط NOT EXISTS را کامنت کن) تا دوباره نتیجه‌ی خالیِ اشتباه را ببینی.

EXISTS در برابر IN و JOIN — کِی کدام؟

روشمناسب براینکته
JOINوقتی به ستون‌های هر دو جدول هم‌زمان نیاز داریاگر رابطه یک‌به‌چند باشد، ممکن است ردیف‌ها تکرار شوند
IN / NOT INمقایسه با یک لیست ساده‌ی مقادیربا NOT IN مراقب NULL باش
EXISTS / NOT EXISTSفقط بررسی «آیا وجود دارد؟»، بدون نیاز به ستون‌های طرف مقابلامن در برابر NULL؛ اغلب سریع‌تر چون به‌محض پیدا شدن اولین تطبیق متوقف می‌شود
نکته‌ی کارایی: EXISTS به‌محض پیدا کردن اولین ردیف تطبیق‌دار، بلافاصله متوقف می‌شود و ادامه نمی‌دهد (کوتاه‌مدار)؛ اما IN معمولاً باید کل لیست زیرپرس‌وجو را حساب کند. روی جدول‌های بزرگ، همین تفاوت می‌تواند محسوس باشد.

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

  • EXISTS فقط TRUE/FALSE برمی‌گرداند و هرگز درگیر UNKNOWN نمی‌شود.
  • NOT EXISTS جایگزین امن NOT IN است، مخصوصاً وقتی احتمال NULL در زیرپرس‌وجو وجود دارد.
  • برای بررسی صرف «آیا رابطه‌ای هست؟»، EXISTS اغلب هم امن‌تر و هم سریع‌تر از IN یا JOIN است.

در درس بعدی سراغ CTE می‌رویم: راهی خواناتر برای نوشتن زیرپرس‌وجوهای پیچیده، به‌خصوص همان‌هایی که در درس قبل به‌عنوان جدول مشتق‌شده دیدیم.