กรองข้อมูลหลังการรวมกลุ่มด้วย HAVING และพลิกข้อมูลของคุณด้วย CASE WHEN ภายในฟังก์ชันการรวมกลุ่ม
เปิดบทเรียนนี้ใน Kodokonคุณรู้จัก GROUP BY อยู่แล้ว บทเรียนนี้จะพูดถึงสิ่งที่แยกคิวรีที่ถูกต้องออกจากคิวรีระดับมืออาชีพ ได้แก่ การกรองหลังการรวมกลุ่ม, การรวมกลุ่มแบบมีเงื่อนไข และความเข้าใจอย่างถ่องแท้เกี่ยวกับลำดับการประเมินผล ในการฝึกฝน ให้เปิด sqliteonline.com (เอนจิน SQLite) หรือเปิด sqlite3 ในเทอร์มินัล แต่ละบทเรียนจะให้คำสั่ง CREATE TABLE และ INSERT ที่คุณต้องใช้ จงคัดลอกชุดข้อมูลนี้ก่อนรันตัวอย่าง
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
category TEXT NOT NULL,
amount REAL NOT NULL,
status TEXT NOT NULL
);
INSERT INTO orders (customer, category, amount, status)
VALUES
('alice', 'books', 42.0, 'paid'),
('alice', 'games', 55.0, 'paid'),
('alice', 'books', 18.5, 'refunded'),
('bruno', 'games', 70.0, 'paid'),
('bruno', 'books', 12.0, 'paid'),
('chloe', 'games', 95.0, 'paid'),
('chloe', 'books', 30.0, 'paid'),
('david', 'books', 8.0, 'refunded');ลำดับการประเมินผลเชิง ตรรกะ คือกุญแจสำคัญ ได้แก่ FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY โดย WHERE กรอง แถว ก่อนการจัดกลุ่ม ส่วน HAVING กรอง กลุ่ม หลังจากคำนวณค่าการรวมกลุ่มเสร็จแล้ว นั่นคือเหตุผลที่ WHERE SUM(amount) > 90 ผิดกฎ เพราะในขั้น WHERE ยังไม่มีผลรวมอยู่เลย ในที่นี้ เราเก็บเฉพาะลูกค้าที่มียอดชำระเงินรวมเกิน 90 (คาดว่า: alice และ chloe)
SELECT customer,
COUNT(*) AS nb_orders,
SUM(amount) AS total
FROM orders
WHERE status = 'paid'
GROUP BY customer
HAVING SUM(amount) > 90;รูปแบบที่ต้องรู้อันที่สองคือ การรวมกลุ่มแบบมีเงื่อนไข (conditional aggregate) ด้วยการสอด CASE WHEN ไว้ภายใน SUM หรือ COUNT คุณสามารถคำนวณหลายเมตริกได้ในการอ่านตารางเพียงรอบเดียว ในขณะที่มือใหม่จะต้องรันคิวรีแยกกันสามครั้ง นี่คือเทคนิคมาตรฐานสำหรับการพลิกแถวให้กลายเป็นคอลัมน์
SELECT customer,
SUM(CASE WHEN category = 'books'
THEN amount ELSE 0 END) AS books_total,
SUM(CASE WHEN category = 'games'
THEN amount ELSE 0 END) AS games_total
FROM orders
WHERE status = 'paid'
GROUP BY customer;