สถานการณ์: รวมราคาต่อ ID
ตัวอย่าง: ตาราง demo84
CREATE TABLE demo84 (id INT, price INT); INSERT INTO demo84 VALUES (1, 2000), (1, 2000), (2, 1800), (2, 2200), (3, 1700);
ข้อมูล
+------+-------+ | id | price | +------+-------+ | 1 | 2000 | | 1 | 2000 | | 2 | 1800 | | 2 | 2200 | | 3 | 1700 | +------+-------+
คำสั่ง: SUM ราคาต่อ ID + กรองผลรวม >= 2000
SELECT id, SUM(price) AS Total FROM demo84 GROUP BY id HAVING SUM(price) >= 2000;
ผลลัพธ์
+------+-------+ | id | Total | +------+-------+ | 1 | 4000 | | 2 | 4000 | +------+-------+
ID 3 (Sum = 1700) ถูกตัดออกด้วย HAVING
ความแตกต่าง WHERE vs HAVING
| Clause | ทำงานเมื่อ | ใช้กับ Aggregate ได้ไหม |
|---|---|---|
| WHERE | ก่อน GROUP BY (Filter Rows) | ไม่ได้ |
| HAVING | หลัง GROUP BY (Filter Groups) | ได้ ✅ |
ลำดับการประมวลผล
1. FROM / JOIN 2. WHERE -- Filter Rows 3. GROUP BY -- Group Rows 4. HAVING -- Filter Groups 5. SELECT -- Choose Columns 6. ORDER BY -- Sort 7. LIMIT -- Limit Rows
ตัวอย่างเพิ่มเติม
1. นับจำนวน Order ต่อ Customer (มี Order > 2)
SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id HAVING COUNT(*) > 2;
2. ยอดขายเฉลี่ยต่อ Product (เฉลี่ย > 1000)
SELECT product_id, AVG(amount) AS avg_sales FROM sales GROUP BY product_id HAVING AVG(amount) > 1000;
3. ใช้ Alias ใน HAVING (MySQL รองรับ)
SELECT id, SUM(price) AS Total FROM demo84 GROUP BY id HAVING Total >= 2000; -- MySQL อนุญาต (Standard SQL ไม่อนุญาต)
ประสิทธิภาพ
- Index บน GROUP BY Column (id) ช่วยเร็วขึ้น
- WHERE กรองก่อน GROUP BY ลดข้อมูลที่ต้อง Aggregate
- หลีกเลี่ยง HAVING ที่ซับซ้อน — คำนวณใน Subquery/CTE ก่อน
MySQL 8.0: Window Function ทางเลือก
SELECT DISTINCT id, SUM(price) OVER (PARTITION BY id) AS Total FROM demo84 QUALIFY SUM(price) OVER (PARTITION BY id) >= 2000;
※ QUALIFY ไม่รองรับใน MySQL (เป็น Snowflake/BigQuery Syntax) — ใช้ Subquery หรือ CTE แทน