HAVING: فیلتر کردن گروهها
در درس قبل، GROUP BY ردیفها را دستهبندی کرد. اما گاهی میخواهیم فقط خود گروهها را فیلتر کنیم — مثلاً «فقط دستههایی که بیش از ۲ محصول دارند» یا «فقط شهرهایی که بیش از یک دانشآموز دارند». اینجا WHERE کافی نیست، چون WHERE روی ردیفهای خام کار میکند، نه روی نتیجهی تجمیعشده.
چرا WHERE نمیتواند نتیجهی COUNT را فیلتر کند
بیا اول ببینیم چرا اینکار جواب نمیدهد:
SELECT category, COUNT(*) AS ProductCount FROM sales WHERE COUNT(*) > 2 GROUP BY category; -- خطا: نمیتوان از تابع تجمیعی داخل WHERE استفاده کرد
علتش همان ترتیب پردازش منطقی است: WHERE پیش از GROUP BY اجرا میشود، یعنی وقتی نوبت به بررسی شرط WHERE میرسد، هنوز هیچ گروهی ساخته نشده و COUNT(*) اصلاً معنایی ندارد. بیا این خطا را با چشم خودت ببینی:
راه درست: HAVING
HAVING دقیقاً همان کار WHERE را انجام میدهد، با یک تفاوت مهم: بعد از GROUP BY اجرا میشود، پس کاملاً میتواند به نتیجهی توابع تجمیعی دسترسی داشته باشد:
SELECT category, COUNT(*) AS ProductCount FROM sales GROUP BY category HAVING COUNT(*) > 2;
بیا این نسخهی درست را امتحان کنیم:
WHERE و HAVING با هم — دو محل فیلتر متفاوت
میتوان هر دو را در یک پرسوجو با هم آورد. WHERE ردیفهای خام را قبل از گروهبندی فیلتر میکند؛ HAVING خودِ گروههای ساختهشده را بعد از آن فیلتر میکند:
SELECT category, SUM(price * quantity) AS Revenue FROM sales WHERE quantity IS NOT NULL -- فیلتر ردیفها، قبل از گروهبندی GROUP BY category HAVING SUM(price * quantity) > 300000 -- فیلتر گروهها، بعد از گروهبندی ORDER BY Revenue DESC;
بیا این را کامل امتحان کنیم:
ترتیب کامل و نهایی بندهای یک پرسوجو
حالا که همهی بندهای اصلی SQL را دیدهای، بیا ترتیب نوشتاری کامل (که باید دقیقاً به همین ترتیب در کد نوشته شود) را مرور کنیم:
SELECT ... FROM ... WHERE ... -- فیلتر ردیفهای خام GROUP BY ... -- دستهبندی HAVING ... -- فیلتر گروهها ORDER BY ...; -- مرتبسازی نتیجهی نهایی
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. همین تفاوت است که توضیح میدهد چرا ORDER BY به نام مستعار SELECT دسترسی دارد ولی WHERE و HAVING ندارند.جمعبندی این درس (و کل فصل ۳)
WHEREنمیتواند مستقیماً روی نتیجهی توابع تجمیعی شرط بگذارد.HAVINGدقیقاً برای همین ساخته شده: فیلتر کردن گروهها بعد ازGROUP BY.WHEREوHAVINGمیتوانند در یک پرسوجو با هم بیایند — هرکدام در جای منطقی خودشان.- ترتیب نوشتاری همیشه:
SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY.
با این درس، فصل ۳ (تجمیع دادهها) کامل شد! از فصل بعدی، وارد یکی از مهمترین مفاهیم SQL میشویم: ارتباط بین جدولها و JOINها — جایی که یاد میگیریم چطور دادهی چند جدول مرتبط را با هم ترکیب کنیم.