WHERE در مقابل HAVING
WHERE ردیفهای خام جدول را پیش از هرگونه گروهبندی (GROUP BY) فیلتر میکند و نمیتواند به توابع تجمیعی مثل SUM یا COUNT ارجاع دهد؛ HAVING گروههای حاصل از GROUP BY را پس از تجمیع فیلتر میکند و دقیقاً برای شرطگذاری روی نتایج توابع تجمیعی ساخته شده است.
| ویژگی | WHERE | HAVING |
|---|---|---|
| زمان اجرا در پردازش Query | قبل از GROUP BY | بعد از GROUP BY |
| دسترسی به توابع تجمیعی | خیر | بله (SUM، COUNT، AVG و...) |
| عملکرد | سریعتر (فیلتر زودهنگام) | کندتر نسبی (بعد از تجمیع کل داده) |
| کاربرد رایج | فیلتر ردیفهای خام | فیلتر گروهها بر اساس تجمیع |
کِی از WHERE استفاده کنیم؟
برای فیلتر کردن ردیفهای تکی بر اساس مقادیر ستونها پیش از هرگونه تجمیع (مثل "فقط سفارشهای سال ۱۴۰۳")، از WHERE استفاده کنید — چون زودتر اجرا میشود و کارآمدتر است.
کِی از HAVING استفاده کنیم؟
برای فیلتر کردن بر اساس نتیجه یک تابع تجمیعی روی گروهها (مثل "فقط مشتریانی که بیش از ۵ سفارش دارند")، از HAVING استفاده کنید چون WHERE به COUNT/SUM دسترسی ندارد.
مثال WHERE
SELECT CustomerId, OrderDate
FROM Orders
WHERE OrderDate >= '2024-03-21'; -- filters raw rows first
مثال HAVING
SELECT CustomerId, COUNT(*) AS OrderCount
FROM Orders
GROUP BY CustomerId
HAVING COUNT(*) > 5; -- filters aggregated groups
اشتباه رایج
تلاش برای نوشتن WHERE COUNT(*) > 5 که با خطای SQL مواجه میشود چون توابع تجمیعی هنوز در مرحله WHERE محاسبه نشدهاند؛ یا برعکس، استفاده غیرضروری از HAVING برای شرطهای ساده روی ستونهای غیرتجمیعی که باعث میشود موتور دیتابیس ابتدا همه ردیفها را گروهبندی کند و سپس فیلتر بزند (کندتر از WHERE).
جمعبندی
فیلتر روی ستونهای خام → WHERE (زودتر و سریعتر)؛ فیلتر روی نتیجه توابع تجمیعی → HAVING (بعد از GROUP BY).
