0Pricing
SQL Interview Prep · บทเรียน

HAVING เทียบกับ WHERE

การกรองก่อนจัดกลุ่มเทียบกับหลังจัดกลุ่ม และส่วนคำสั่งใดมองเห็นค่ารวม

HAVING เทียบกับ WHERE เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คำถามที่คุณจะได้รับ

คำถามว่า ‘WHERE และ HAVING แตกต่างกันอย่างไร’ เป็นหนึ่งในคำถามสัมภาษณ์งานด้านเอสคิวแอลที่ถูกถามบ่อยที่สุด คำตอบที่ยังไม่ดีพอคือ ‘HAVING ใช้กับค่ารวม’ ส่วนคำตอบที่ดีจะอธิบายว่า แต่ละส่วนคำสั่งทำงานเมื่อใด ในกระบวนการประมวลผลของคำสั่งสอบถาม

ช่วงเวลานั้นคือหัวใจทั้งหมด: WHERE กรองแถว ก่อนการจัดกลุ่ม ส่วน HAVING กรองกลุ่ม หลังการรวมค่า

ตำแหน่งในลำดับการทำงาน

ทบทวนลำดับการทำงานเชิงตรรกะของคำสั่งสอบถาม:

  • FROM / JOIN → สร้างชุดแถว
  • WHERE → กรองแถวแต่ละแถว
  • GROUP BY → รวมแถวให้เป็นกลุ่ม
  • HAVING → กรองกลุ่ม
  • SELECT → เลือกคอลัมน์
  • ORDER BY → เรียงลำดับ

WHERE ทำงานก่อนที่กลุ่มจะมีอยู่ ส่วน HAVING ทำงานภายหลัง ดังนั้น HAVING จึงมองเห็นค่ารวมได้ แต่ WHERE มองไม่เห็น

WHERE มองไม่เห็นค่ารวม

เนื่องจาก WHERE ทำงานก่อนการจัดกลุ่ม จึงยังไม่มีค่ารวมให้ใช้ การเขียน WHERE COUNT(*) > 5 ถือเป็นข้อผิดพลาดทางไวยากรณ์ในฐานข้อมูลมาตรฐานทุกระบบ

ผู้สัมภาษณ์มักใส่บรรทัดนี้มาโดยเฉพาะเพื่อทดสอบว่าคุณเข้าใจกระบวนการประมวลผลหรือไม่ ค่ารวมยังไม่มีอยู่ในขณะที่ WHERE ถูกประเมินผล

-- ERROR: aggregate not allowed in WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;

HAVING กรองกลุ่ม

ย้ายเงื่อนไขเกี่ยวกับค่ารวมไปไว้ใน HAVING แล้วคำสั่งจะทำงานได้ เพราะ HAVING ทำงานหลังจากสร้างกลุ่มและคำนวณค่ารวมของกลุ่มแล้ว

ให้ตีความว่า ‘จัดกลุ่มพนักงานก่อน แล้วเก็บไว้เฉพาะแผนกที่มีจำนวนมากกว่าห้า’

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;

ใส่ตัวกรองแถวไว้ใน WHERE

ข้อผิดพลาดในทางกลับกันคือการกรองแถวดิบด้วย HAVING แม้มักให้คำตอบถูกต้อง แต่จะ ช้ากว่าและทำให้เข้าใจผิด เพราะคุณจัดกลุ่มแถวที่ตั้งใจจะทิ้งไปแล้ว

หลักจำง่าย ๆ: กรองจาก ค่าของคอลัมน์ดิบ → WHERE กรองจาก ค่ารวม → HAVING การกรองแถวตั้งแต่เนิ่น ๆ จะลดปริมาณข้อมูลที่การจัดกลุ่มต้องประมวลผล

-- Better: drop inactive rows BEFORE grouping
SELECT department, COUNT(*) AS headcount
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING COUNT(*) > 5;

ใช้ทั้งสองส่วนคำสั่งร่วมกัน

คำสั่งสอบถามที่สมบูรณ์มักใช้ทั้งสองส่วนคำสั่ง WHERE จะจำกัดแถวก่อน จากนั้น HAVING จะเก็บเฉพาะกลุ่มที่ตรงตามเงื่อนไข การอ่านจากบนลงล่างสอดคล้องกับลำดับการทำงานเชิงตรรกะ

ตัวอย่าง: จากคำสั่งซื้อที่ทำรายการในปีนี้ ให้ค้นหาลูกค้าที่ใช้จ่ายรวมมากกว่า 1000

SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000;

HAVING กับคอลัมน์ที่ไม่ได้รวมค่า

HAVING สามารถอ้างอิงคอลัมน์ที่ใช้จัดกลุ่มได้ ไม่ได้จำกัดเฉพาะค่ารวมเท่านั้น HAVING department = 'Sales' เป็นคำสั่งที่ถูกต้อง แต่ไม่มีประโยชน์ เพราะควรใส่ตัวกรองนี้ไว้ใน WHERE เพื่อให้ทำงานเร็วกว่า

หากผู้สัมภาษณ์แสดง HAVING ที่กรองคอลัมน์ธรรมดาซึ่งใช้จัดกลุ่ม คำวิจารณ์ที่คาดหวังคือ ‘ย้ายไปไว้ใน WHERE เพื่อเพิ่มประสิทธิภาพ’

-- Works but inefficient; prefer WHERE department = 'Sales'
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Sales';

HAVING โดยไม่มี GROUP BY

กรณีที่ละเอียดอ่อนคือ HAVING สามารถใช้ได้แม้ไม่มี GROUP BY ทั้งตารางจะกลายเป็นกลุ่มโดยนัยเพียงกลุ่มเดียว และ HAVING จะกรองกลุ่มนั้น

หากเงื่อนไขค่ารวมเป็นเท็จ คุณจะได้ ศูนย์แถว แต่หากเป็นจริง คุณจะได้หนึ่งแถว กรณีนี้ไม่ค่อยมีประโยชน์นัก แต่ผู้สัมภาษณ์มักถามเพื่อยืนยันว่าคุณเข้าใจแนวคิดเรื่องกลุ่มโดยนัย

-- Returns the count only if the table has > 100 rows
SELECT COUNT(*) AS total
FROM orders
HAVING COUNT(*) > 100;

HAVING ใช้ชื่อแทนจาก SELECT ได้หรือไม่

เช่นเดียวกับกลเม็ดเรื่องขอบเขตของชื่อแทนในส่วนอื่น ระบบฐานข้อมูลแต่ละแบบมีพฤติกรรมต่างกัน โพสต์เกรสและ MySQL อนุญาตให้ HAVING อ้างอิงชื่อแทนจาก SELECT ได้ ส่วน เซิร์ฟเวอร์เอสคิวแอลและออราเคิล ไม่อนุญาต

แนวทางที่ใช้ได้กับทุกระบบคือเขียนนิพจน์ค่ารวมซ้ำใน HAVING วิธีนี้ทำงานได้กับทุกกลไกฐานข้อมูลและช่วยหลีกเลี่ยงปัญหาในการสัมภาษณ์ที่ครอบคลุมหลายฐานข้อมูล

-- Portable: repeat the aggregate, do not rely on the alias
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region
HAVING SUM(amount) > 5000;

มุมมองด้านประสิทธิภาพ

หากต้องการตอบให้โดดเด่น ให้เชื่อมโยงส่วนคำสั่งเข้ากับประสิทธิภาพ: WHERE ลดจำนวนแถวที่กลไกจัดกลุ่มต้องสแกนและสามารถใช้ดัชนีได้ ส่วน HAVING ทำงานกับกลุ่มที่รวมค่าแล้ว จึงไม่สามารถลดต้นทุนการจัดกลุ่มได้

ประเด็นที่ผู้สัมภาษณ์ต้องการฟังคือ เลื่อนตัวกรองทุกตัวไปไว้ให้เร็วที่สุดเท่าที่ทำได้ เฉพาะเงื่อนไขที่ขึ้นอยู่กับค่ารวมจริง ๆ เท่านั้นที่ต้องใช้ HAVING

คำตอบหนึ่งประโยค

จดจำประโยคนี้ไว้สำหรับการสัมภาษณ์: ‘WHERE กรองแถวก่อนการจัดกลุ่มและมองไม่เห็นค่ารวม ส่วน HAVING กรองกลุ่มหลังการรวมค่า และเป็นส่วนคำสั่งเดียวที่ใช้ตรวจสอบค่ารวมได้’

ตามด้วยรายการลำดับการทำงาน เพียงเท่านี้คุณก็จะให้คำตอบที่ครบถ้วนและฟังดูเป็นมืออาชีพ

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ตัดสินใจว่าแต่ละเงื่อนไขควรอยู่ในส่วนคำสั่งใด

สรุปทบทวน

WHERE: กรองแถวก่อน GROUP BY และห้ามใช้ค่ารวม HAVING: กรองกลุ่มหลังการรวมค่า และเป็นตำแหน่งเดียวที่อนุญาตให้ใช้เงื่อนไขค่ารวม

  • ใส่ตัวกรองคอลัมน์ดิบไว้ใน WHERE เพื่อความเร็วและการใช้ดัชนี
  • HAVING สามารถอ้างอิงคอลัมน์ที่จัดกลุ่มได้ แต่ไม่ควรใช้กับตัวกรองทั่วไป
  • HAVING ทำงานได้โดยไม่มี GROUP BY โดยใช้กลุ่มโดยนัยของทั้งตาราง
  • เขียนนิพจน์ค่ารวมซ้ำใน HAVING เพื่อความปลอดภัยเมื่อใช้กับระบบฐานข้อมูลหลายแบบ

คำถามที่พบบ่อย

บทเรียน “HAVING เทียบกับ WHERE” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “HAVING เทียบกับ WHERE” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “HAVING เทียบกับ WHERE”

การกรองก่อนจัดกลุ่มเทียบกับหลังจัดกลุ่ม และส่วนคำสั่งใดมองเห็นค่ารวม คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “HAVING เทียบกับ WHERE” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม

ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. กฎ GROUP BY สำหรับคอลัมน์ใน SELECT
  2. HAVING เทียบกับ WHERE
  3. จัดกลุ่มด้วยหลายคอลัมน์และนิพจน์
  4. นับและกรองกลุ่ม
← กลับไปที่ SQL Interview Prep