ทำความเข้าใจเรื่องการสรุปข้อมูลในฐานข้อมูล
เวลาเราเก็บข้อมูลไว้ใน PostgreSQL (ระบบจัดการฐานข้อมูลแบบตาราง) เรามักจะมีข้อมูลจำนวนมหาศาล ถ้าเราอยากรู้ภาพรวม เช่น ยอดขายรวมหรือจำนวนพนักงาน การนั่งไล่ดูทีละแถวคงไม่ไหว เราจึงต้องใช้สิ่งที่เรียกว่า Aggregate Functions (ชุดคำสั่งสำหรับคำนวณสรุปค่า) เพื่อจัดการเรื่องนี้
ลองนึกภาพว่าคุณเป็นเจ้าของร้านขายผลไม้ คุณมีสมุดจดที่บันทึกการขายทุกรายการตลอดทั้งปี ถ้าอยากรู้ว่าขายไปทั้งหมดกี่ลูก หรือขายได้เงินรวมเท่าไหร่ คุณคงไม่มานั่งนับมือทีละบรรทัดใช่ไหม Aggregate ก็ทำหน้าที่เหมือนเครื่องคิดเลขที่ดึงข้อมูลจากหลายแถวมารวมกันให้เหลือเพียงค่าเดียวที่น่าสนใจ
ในการเขียนโปรแกรมจริง ฐานข้อมูลคือคลังสมบัติที่เก็บข้อมูลผู้ใช้หรือยอดสั่งซื้อ การดึงข้อมูลมาคำนวณที่ฝั่งฐานข้อมูลโดยตรงจะเร็วกว่าการดึงข้อมูลทั้งหมดไปคำนวณที่ตัวโปรแกรม เพราะมันช่วยลดภาระการรับส่งข้อมูลระหว่างเซิร์ฟเวอร์ (เครื่องคอมพิวเตอร์ที่เก็บข้อมูลหลัก) กับแอปพลิเคชันของคุณได้มหาศาลเลยล่ะ
รู้จักกับคำสั่งคำนวณพื้นฐาน
คำสั่งหลักที่เราใช้บ่อยที่สุดมีอยู่ 5 ตัว ได้แก่ COUNT (นับจำนวน), SUM (รวมเลข), AVG (หาค่าเฉลี่ย), MIN (หาค่าต่ำสุด) และ MAX (หาค่าสูงสุด) คำสั่งเหล่านี้จะช่วยให้เราตอบคำถามทางธุรกิจได้ทันทีโดยไม่ต้องเขียนโค้ดซับซ้อน
สมมติว่าเรามีตารางชื่อ sales ที่เก็บราคาสินค้าไว้ในคอลัมน์ (ช่องแนวตั้งในตาราง) ชื่อ price เราสามารถเขียนคำสั่งดึงข้อมูลสรุปออกมาได้ดังนี้
-- นับจำนวนรายการขายทั้งหมด
SELECT COUNT(*) FROM sales;
-- หาผลรวมยอดขายและค่าเฉลี่ย
SELECT SUM(price), AVG(price) FROM sales;
-- หาค่าราคาต่ำสุดและสูงสุด
SELECT MIN(price), MAX(price) FROM sales;
คำสั่ง COUNT(*) จะนับทุกแถวที่มีในตาราง ส่วน SUM(price) จะเอาค่าในคอลัมน์ price ทุกแถวมารวมกัน คำสั่ง AVG จะหาค่ากลาง MIN หาตัวที่น้อยที่สุด และ MAX หาตัวที่มากที่สุด ผลลัพธ์ที่ได้จะเป็นตารางที่มีแถวเดียวซึ่งแสดงค่าสรุปตามที่เราสั่งไป
จัดกลุ่มข้อมูลด้วย GROUP BY
บ่อยครั้งที่เราไม่ได้อยากรู้ผลรวมทั้งตาราง แต่อยากรู้แยกตามกลุ่ม เช่น อยากรู้ว่าผลไม้แต่ละชนิดขายได้กี่ลูก เราจึงต้องใช้ GROUP BY (คำสั่งแบ่งกลุ่มข้อมูลตามค่าที่กำหนด) เพื่อจับคู่ข้อมูลที่เหมือนกันเข้าด้วยกันก่อนที่จะนำไปคำนวณ
ถ้าคุณมีตาราง sales ที่มีคอลัมน์ fruit_name (ชื่อผลไม้) และ price คุณสามารถจัดกลุ่มตามชื่อผลไม้เพื่อดูยอดขายรวมของแต่ละชนิดได้ การทำแบบนี้จะช่วยให้ข้อมูลดูง่ายและนำไปใช้ทำรายงานต่อได้ทันที
-- รวมยอดขายแยกตามชื่อผลไม้
SELECT fruit_name, SUM(price)
FROM sales
GROUP BY fruit_name;
ในโค้ดนี้ GROUP BY fruit_name จะบอกให้ฐานข้อมูลจับกลุ่มแถวที่มีชื่อผลไม้เดียวกันไว้ด้วยกันก่อน จากนั้น SUM(price) จะทำหน้าที่คำนวณยอดรวมแยกตามกลุ่มที่แบ่งไว้ ผลลัพธ์ที่ได้คือรายชื่อผลไม้แต่ละอย่างและยอดเงินรวมของมัน
การกรองกลุ่มด้วย HAVING
บางครั้งเมื่อเราจัดกลุ่มแล้ว เราอาจต้องการเลือกดูเฉพาะกลุ่มที่ตรงเงื่อนไขเท่านั้น เช่น อยากดูเฉพาะผลไม้ที่มียอดขายรวมเกิน 1,000 บาท เราจะใช้ HAVING (คำสั่งกรองข้อมูลหลังจากจัดกลุ่มแล้ว) มาช่วยในการคัดกรอง
หลายคนมักสับสนระหว่าง WHERE กับ HAVING แต่ให้จำง่ายๆ ว่า WHERE ใช้กรองข้อมูลก่อนจัดกลุ่ม ส่วน HAVING ใช้กรองผลลัพธ์ที่จัดกลุ่มเสร็จเรียบร้อยแล้ว ถ้าคุณพยายามใช้ WHERE มากรองผลรวม ฐานข้อมูลจะแจ้งเตือนข้อผิดพลาดทันที
-- กรองเฉพาะผลไม้ที่มียอดขายรวมเกิน 1,000 บาท
SELECT fruit_name, SUM(price)
FROM sales
GROUP BY fruit_name
HAVING SUM(price) > 1000;
บรรทัด HAVING SUM(price) > 1000 จะเช็คผลรวมของแต่ละกลุ่มที่คำนวณได้ ถ้ากลุ่มไหนมียอดไม่ถึง 1,000 บาท มันจะถูกตัดทิ้งไปจากผลลัพธ์ที่แสดงให้คุณเห็น ผลลัพธ์ที่ควรจะได้คือตารางที่มีชื่อผลไม้และยอดขายที่ผ่านเงื่อนไขนี้เท่านั้น
การกรองข้อมูลด้วย WHERE
ก่อนจะถึงขั้นตอนการจัดกลุ่ม เรามักต้องกรองข้อมูลดิบออกก่อนด้วย WHERE (คำสั่งกรองข้อมูลก่อนการประมวลผล) เช่น ถ้าเราอยากนับยอดขายของปีนี้เท่านั้น เราต้องใช้ WHERE เพื่อตัดข้อมูลของปีเก่าๆ ทิ้งไปตั้งแต่นับแถว
การใช้ WHERE ตั้งแต่ต้นจะช่วยให้ฐานข้อมูลทำงานเร็วขึ้น เพราะไม่ต้องนำข้อมูลที่ไม่จำเป็นเข้าสู่ขั้นตอนการจัดกลุ่มหรือคำนวณ นี่คือแนวปฏิบัติที่ดีในการเขียน Query (คำสั่งถามข้อมูล) เพื่อให้แอปพลิเคชันของเราทำงานได้รวดเร็วที่สุด
-- นับยอดขายของแอปเปิ้ลในปี 2023 เท่านั้น
SELECT COUNT(*)
FROM sales
WHERE fruit_name = 'Apple' AND sale_date >= '2023-01-01';
โค้ดนี้ใช้ WHERE เพื่อเลือกเฉพาะแถวที่เป็น 'Apple' และวันที่มากกว่าหรือเท่ากับวันที่หนึ่งมกราคมปี 2023 ก่อนจะทำการ COUNT ข้อมูลที่เหลือ ผลลัพธ์ที่ได้จะเป็นตัวเลขจำนวนแถวที่ผ่านเงื่อนไขการกรองทั้งหมดนี้
ข้อควรระวังสำหรับมือใหม่
มือใหม่มักจะพลาดเรื่องการใช้คอลัมน์ที่ไม่ได้รับอนุญาตใน SELECT ถ้าคุณใช้ GROUP BY คอลัมน์ที่ปรากฏใน SELECT ต้องเป็นคอลัมน์ที่อยู่ใน GROUP BY หรือต้องเป็นคอลัมน์ที่อยู่ในฟังก์ชันคำนวณเท่านั้น ห้ามใส่คอลัมน์มั่วๆ เข้าไปเด็ดขาด
อีกเรื่องที่พบบ่อยคือการลืมลำดับของคำสั่ง ฐานข้อมูลอ่านคำสั่งตามลำดับ คือ FROM -> WHERE -> GROUP BY -> HAVING -> SELECT การจำลำดับนี้ได้จะช่วยให้คุณออกแบบโค้ดได้แม่นยำและแก้ปัญหาได้เร็วเวลาเจอข้อผิดพลาด อย่าลืมทดสอบคำสั่งกับข้อมูลจำลองก่อนรันบนฐานข้อมูลจริงเสมอ
สุดท้าย ให้ระวังเรื่องค่า NULL (ค่าว่างหรือไม่มีข้อมูล) ในคอลัมน์ที่นำมาคำนวณ โดยปกติ COUNT(*) จะนับแถวทั้งหมด แต่ COUNT(column_name) จะนับเฉพาะแถวที่ข้อมูลในคอลัมน์นั้นไม่เป็น NULL ซึ่งอาจทำให้ตัวเลขสรุปออกมาไม่เท่ากันหากข้อมูลในตารางไม่สมบูรณ์
สรุปการนำไปใช้จริง
เมื่อคุณต้องสร้างระบบรายงานผลหลังบ้าน (Dashboard) ให้ผู้ใช้งาน คุณจะได้ใช้ทักษะเหล่านี้แน่นอน เช่น การทำกราฟแสดงยอดขายรายเดือน คุณต้องใช้ GROUP BY ตามเดือนและใช้ SUM เพื่อรวมยอดเงิน การฝึกฝนเรื่องนี้จะทำให้คุณจัดการข้อมูลได้อย่างมืออาชีพ
ลองเริ่มทำโปรเจกต์เล็กๆ เช่น เก็บรายชื่อเกมที่คุณเล่นและคะแนนที่ทำได้ในแต่ละวัน แล้วลองเขียน Query เพื่อหาคะแนนเฉลี่ยหรือคะแนนสูงสุดของเกมแต่ละชื่อ การลงมือทำจริงแบบนี้จะทำให้คุณเข้าใจตรรกะการจัดกลุ่มข้อมูลได้ลึกซึ้งกว่าการอ่านตำราเพียงอย่างเดียว
จำไว้ว่าการเป็นโปรแกรมเมอร์ไม่ได้อยู่ที่การจำคำสั่งได้ทั้งหมด แต่อยู่ที่การรู้วิธีเลือกใช้เครื่องมือให้เหมาะกับสถานการณ์ การฝึกเขียนคำสั่ง SQL (ภาษาสำหรับจัดการฐานข้อมูล) ให้คล่องเป็นพื้นฐานสำคัญ ที่จะช่วยให้คุณต่อยอดไปสู่การจัดการข้อมูลที่ซับซ้อนขึ้นในอนาคตได้อย่างมั่นใจแน่นอน