EXISTS: بررسی وجود رابطه، بدون تلهی NULL
در درس قبل دیدیم NOT IN با یک NULL داخل زیرپرسوجو، بیسروصدا و بدون خطا، نتیجهی کاملاً خالی میدهد. EXISTS دقیقاً همان سوال را میپرسد — «آیا رابطهای وجود دارد؟» — اما با روشی که این مشکل را ندارد.
EXISTS دقیقاً چه میکند؟
EXISTS فقط بررسی میکند آیا زیرپرسوجو حداقل یک ردیف برمیگرداند یا نه — نتیجهاش همیشه TRUE یا FALSE است، هیچوقت UNKNOWN. برخلاف IN، اصلاً به مقادیر داخل زیرپرسوجو کاری ندارد؛ فقط میپرسد چیزی پیدا شد یا نه.
-- دانشآموزانی که حداقل در یک درس ثبتنام کردهاند SELECT full_name FROM students s WHERE EXISTS ( SELECT 1 FROM enrollments e WHERE e.student_id = s.id );
نکتهی ظریف: داخل زیرپرسوجوی EXISTS معمولاً بهجای نام ستون، همان SELECT 1 نوشته میشود — چون مقدار واقعی ستونها اصلاً مهم نیست، فقط وجود ردیف مهم است. بیا امتحان کنیم:
NOT EXISTS — جایگزین امن NOT IN
حالا بیا دقیقاً همان پرسوجوی «کدام درسها هیچ دانشآموزی ندارند؟» را از درس قبل، اینبار با NOT EXISTS بازنویسی کنیم و کنار نسخهی NOT IN بگذاریم:
-- همان سوال قبلی، اینبار امن: SELECT title FROM courses c WHERE NOT EXISTS ( SELECT 1 FROM enrollments e WHERE e.course_id = c.id );
بیا هر دو نسخه را دقیقاً روی همان دادهای که در درس قبل تلهاش را دیدیم، کنار هم اجرا کنیم:
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 میرویم: راهی خواناتر برای نوشتن زیرپرسوجوهای پیچیده، بهخصوص همانهایی که در درس قبل بهعنوان جدول مشتقشده دیدیم.