การนับจำนวนแต่ละค่าในคอลัมน์เดียวด้วย CASE WHEN และ SUM()
เมื่อต้องการนับจำนวนของแต่ละค่าที่แตกต่างกันในคอลัมน์เดียว และแสดงผลในคอลัมน์แยกกัน ให้ใช้ CASE WHEN ภายใน SUM() ร่วมกับ GROUP BY
รูปแบบคำสั่ง
SELECT
group_column,
SUM(CASE WHEN target_column = value1 THEN 1 ELSE 0 END) AS alias1,
SUM(CASE WHEN target_column = value2 THEN 1 ELSE 0 END) AS alias2,
...
FROM table_name
GROUP BY group_column;
ตัวอย่าง: นับจำนวน Product Rating แต่ละระดับ (1, 2, 3) แยกตามสินค้า
1. สร้างตารางและเพิ่มข้อมูล
CREATE TABLE DemoTable (
ProductName VARCHAR(100),
ProductRating ENUM('1', '2', '3')
);
INSERT INTO DemoTable VALUES ('Product-1', 3);
INSERT INTO DemoTable VALUES ('Product-2', 1);
INSERT INTO DemoTable VALUES ('Product-3', 2);
INSERT INTO DemoTable VALUES ('Product-1', 2);
INSERT INTO DemoTable VALUES ('Product-3', 3);
INSERT INTO DemoTable VALUES ('Product-2', 2);
INSERT INTO DemoTable VALUES ('Product-3', 3);
2. ดูข้อมูลทั้งหมด
SELECT * FROM DemoTable;
ผลลัพธ์:
+-------------+---------------+
| ProductName | ProductRating |
+-------------+---------------+
| Product-1 | 3 |
| Product-2 | 1 |
| Product-3 | 2 |
| Product-1 | 2 |
| Product-3 | 3 |
| Product-2 | 2 |
| Product-3 | 3 |
+-------------+---------------+
3. นับจำนวน Rating แต่ละระดับ แยกตามสินค้า
SELECT
ProductName,
SUM(CASE WHEN ProductRating = 3 THEN 1 ELSE 0 END) AS Rating_3_Count,
SUM(CASE WHEN ProductRating = 2 THEN 1 ELSE 0 END) AS Rating_2_Count,
SUM(CASE WHEN ProductRating = 1 THEN 1 ELSE 0 END) AS Rating_1_Count
FROM DemoTable
GROUP BY ProductName;
ผลลัพธ์:
+-------------+----------------+----------------+----------------+
| ProductName | Rating_3_Count | Rating_2_Count | Rating_1_Count |
+-------------+----------------+----------------+----------------+
| Product-1 | 1 | 1 | 0 |
| Product-2 | 0 | 1 | 1 |
| Product-3 | 2 | 1 | 0 |
+-------------+----------------+----------------+----------------+
การอธิบาย
CASE WHEN ProductRating = 3 THEN 1 ELSE 0 ENDสร้างคอลัมน์เสมือนที่มีค่า 1 ถ้า Rating=3 มิฉะนั้น 0SUM()รวมค่า 1 และ 0 → ได้จำนวนแถวที่ Rating=3GROUP BY ProductNameแยกการนับตามสินค้า
วิธีอื่น: Pivot Table ด้วย Conditional Aggregation
วิธีนี้เรียกว่า "Conditional Aggregation" หรือ "Pivot Query" เป็นเทคนิคมาตรฐานใน SQL สำหรับแปลงแถวเป็นคอลัมน์
MySQL 8.0+ : ใช้ FILTER Clause (ถ้ารองรับ)
SELECT
ProductName,
COUNT(*) FILTER (WHERE ProductRating = 3) AS Rating_3_Count,
COUNT(*) FILTER (WHERE ProductRating = 2) AS Rating_2_Count,
COUNT(*) FILTER (WHERE ProductRating = 1) AS Rating_1_Count
FROM DemoTable
GROUP BY ProductName;
หมายเหตุ: MySQL ยังไม่รองรับ FILTER clause อย่างเต็มที่ (รองรับใน PostgreSQL, SQLite ใหม่ๆ) ควรใช้วิธี CASE WHEN
การขยาย: คำนวณเปอร์เซ็นต์พร้อมกัน
SELECT
ProductName,
COUNT(*) AS Total_Ratings,
SUM(CASE WHEN ProductRating = 3 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) AS Pct_3_Stars,
SUM(CASE WHEN ProductRating = 2 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) AS Pct_2_Stars,
SUM(CASE WHEN ProductRating = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) AS Pct_1_Star
FROM DemoTable
GROUP BY ProductName;