ความแตกต่างระหว่าง ประโยค HAVING กับ ประโยค WHERE

สำหรับบทความนี้ ผู้เขียนเคยได้รับคำถามเกี่ยวกับความแตกต่างระหว่างประโยค HAVING กับประโยค WHERE ในคำสั่ง SELECT ค่อนข้างบ่อย ดังนั้น เพื่อความกระจ่างแก่ผู้อ่าน จึง ขอยกเรื่องลำดับในการประมวลผลของประโยคต่าง ๆ ในคำสั่ง SELECT มาให้ทบทวน หรือ ทำความเข้าใจกัน
ความแตกต่างระหว่าง ประโยค HAVING กับ ประโยค WHERE
ทักษะ (ระบุได้หลายทักษะ)

ความแตกต่างระหว่าง ประโยค HAVING  กับ ประโยค WHERE


สำหรับบทความนี้ ผู้เขียนเคยได้รับคำถามเกี่ยวกับความแตกต่างระหว่างประโยค HAVING กับประโยค WHERE ในคำสั่ง SELECT ค่อนข้างบ่อย
ดังนั้น เพื่อความกระจ่างแก่ผู้อ่าน จึง ขอยกเรื่องลำดับในการประมวลผลของประโยคต่าง ๆ ในคำสั่ง SELECT มาให้ทบทวน หรือ ทำความเข้าใจกัน
ดังตารางต่อไปนี้

ตารางแสดงลำดับการประมวลผลคำสั่ง SELECT

ตารางแสดงลำดับการประมวลผลคำสั่ง SELECT

ที่ผู้เขียนต้องปูพื้นฐานเกี่ยวกับลำดับการประมวลผลในคำสั่ง SELECT นั้น
เป็นเพราะมีผู้อ่านจำนวนไม่น้อยเลย ที่เข้าใจว่าคำสั่ง SELECT จะมีลำดับการประมวลผลจากประโยค SELECT เป็นลำดับแรก

แต่หากดูจาก ตารางแสดงลำดับการประมวลผลคำสั่ง SELECT จะพบว่า
ประโยค SELECT นั้นได้รับการประมวลผลเป็นลำดับที่ 5 เสียด้วยซ้ำ
(ผู้เขียนเรียกคำสั่ง SELECT หมายถึงทั้งคำสั่งในการ Query แต่ หากเรียกว่าประโยค SELECT จะหมายถึง คำว่า “SELECT” เพียงคำเดียวจากทั้งหมดที่จะประกอบด้วย FROM, WHERE, GROUP BY, HAVING และ ORDER BY  ขอผู้อ่านอย่าสับสน)

ผู้เขียนขอยกตัวอย่างให้เห็นอย่างง่าย ๆ ดังนี้
 

FROM, WHERE, GROUP BY, HAVING,ORDER BY

จากรูปจะเห็นว่าผู้เขียนได้ตั้งชื่อเล่น (Alias) ให้กับตารางในประโยค FROM แล้วจึงนำไปอ้างอิงถึงในประโยค WHERE และ SELECT
หากลำดับการประมวลผลทำจากบนลงล่างอย่างหลายคนเข้าใจ  Query นี้คงจะฟ้องข้อผิดพลาดออกมา เพราะมีการนำชื่อเล่นไปใช้ก่อน ที่จะประกาศให้มีชื่อเล่นเสียด้วยซ้ำ

แต่ Query นี้ประมวลผลผ่านฉลุย ไม่ฟ้องข้อผิดพลาดแต่ประการใด เพราะหากพิจารณาตาม ตารางแสดงลำดับการประมวลผลคำสั่ง SELECT
จะเห็นว่าการประกาศชื่อเล่นให้กับตารางนั้น ทำในประโยค FROM ซึ่งได้รับการประมวลผลเป็นลำดับที่ 1 แล้ว
จึงนำชื่อเล่นที่ประกาศไปใช้งานในประโยค SELECT ซึ่งถูกประมวลผลเป็นลำดับที่ 5 เลยสามารถกระทำได้
 
คราวนี้กลับมาที่ประโยค WHERE กับ HAVING ต่างกันตรงไหน เพราะทั้งสองประโยคใช้เป็น <Search Condition> ด้วยกันทั้งคู่
จาก ตารางแสดงลำดับการประมวลผลคำสั่ง SELECT จะเห็นว่า

ประโยค WHERE นั้นมีลำดับการประมวลผลเป็นลำดับที่ 2 ถัดจากประโยค FROM

แต่ HAVING นั้นมีลำดับการประมวลผลเป็นลำดับที่ 4 ถัดจากประโยค GROUP BY

นั่นหมายความว่าประโยค WHERE จะใช้กรองผลลัพธ์จากประโยค FROM ก่อนที่ส่งต่อผลลัพธ์นั้นเข้าประมวลผลในประโยค GROUP BY
จากนั้นประโยค HAVING จึงกรองผลลัพธ์ที่ได้จากประโยค GROUP BY อีกทอดหนึ่ง

ผู้เขียนได้แสดงให้เห็นผลลัพธ์ข้อมูล เทียบเคียงลำดับในการประมวลผล ได้ผลดังต่อไปนี้

ลำดับที่ 1 SELECT ข้อมูลพนักงานทุกแถวข้อมูล โดย Query ต่อไปนี้

SELECT ข้อมูลพนักงานทุกแถวข้อมูล

ผลลัพธ์ที่ได้คือ

ผลลัพธ์จากการ Query

จะเห็นว่าผลลัพธ์มีทั้งหมด 31,465 แถวข้อมูล เป็นข้อมูลยอดขายแต่ละรายการขาย
โดยประกอบด้วยเลขที่การขาย, เลขที่ใบสั่งซื้อ, เลขประจำตัวพนักงานขาย, ยอดขาย และวันที่ขาย
จะเห็นได้ว่าบางรายการขายนั้นไม่มีเลขที่ใบสั่งซื้อ และเลขประจำตัวพนักงานขาย เนื่องมาจากเป็นการขายผ่านอินเตอร์เน็ต

ลำดับที่ 2 กรองข้อมูลด้วยประโยค WHERE โดย Query ต่อไปนี้

กรองข้อมูลด้วยประโยค WHERE

ผลลัพธ์ที่ได้คือ

ผลลัพธ์จากการ Query โดยใช้ WHERE

จะเห็นว่าผลลัพธ์เหลือเพียง 12,443 แถวข้อมูล จากประโยค WHERE ที่เพิ่มเข้าไป

ลำดับที่ 3 รวมกลุ่มข้อมูลที่กรองมาแล้ว (ประโยค WHERE) ด้วยประโยค GROUP BY โดย Query ต่อไปนี้

รวมกลุ่มข้อมูลที่กรองมาแล้ว (ประโยค WHERE) ด้วยประโยค GROUP BY

Query ดังกล่าวเป็นการรวมกลุ่มงานขายของพนักงานขายแต่ละคนเข้าด้วยกัน
โดยงานขายใดระบุพนักงานขายไม่ได้ในไปรวมกันอยู่ใน Internet Sales

ผลลัพธ์ที่ได้คือ

จัดกลุ่มข้อมูลด้วย GROUP BY

จะเห็นว่าเมื่อรวมกลุ่มข้อมูลแล้วเหลือเพียง 18 แถวข้อมูลเท่านั้น

ลำดับที่ 4 กรองข้อมูลที่รวมกลุ่มแล้วด้วยประโยค HAVING โดย Query ต่อไปนี้

กรองข้อมูลที่รวมกลุ่มแล้วด้วยประโยค HAVING

ผลลัพธ์ที่ได้คือ

ผลลัพธ์ที่ได้เหลือเพียง 5 แถวข้อมูลเป็น แถวข้อมูลที่มียอดรวม (เกิดจากประโยค GROUP BY ก่อนหน้า) เกินกว่า 3 ล้าน

ผลลัพธ์ที่ได้เหลือเพียง 5 แถวข้อมูลเป็น แถวข้อมูลที่มียอดรวม (เกิดจากประโยค GROUP BY ก่อนหน้า) เกินกว่า 3 ล้าน

สรุป

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

ผู้อ่านคงจะพอเห็นประโยชน์ของทั้งสองประโยค แม้ว่าจะเป็น <Search Condition> ด้วยกันทั้งคู่
แต่เมื่อทำในลำดับการประมวลผลที่ต่างกันแล้ว ก็สามารถนำไปใช้ประโยชน์กันคนละแบบ

หากผู้อ่านยังสงสัยอยู่ให้ลองนำเอา Query ในแต่ละลำดับขั้นตอนที่ผู้เขียนนำเสนอไว้นี้ ไปทดลองกับฐานข้อมูล AdventureWorks เองอีกครั้งเพื่อความเข้าใจ

แต่สิ่งที่ผู้เขียนอยากให้ผู้อ่านคำนึงถึง และเห็นจะเป็นประโยชน์มากกว่า  ก็คือ

ลำดับการประมวลผลคำสั่ง SELECT เพราะหากผู้อ่านแม่นยำในลำดับดังกล่าว
การเขียน Query ของผู้อ่านก็จะง่าย และ สามารถมองภาพรวมออกเสมอ ด้วยความปรารถนาดี

 

บทความโดย
อาจารย์ภัคพงศ์ กฤตวัฒน์
วิทยากรดูแลและออกแบบหลักสูตร
กลุ่มวิชา SQL Server/Window Server