Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

รวมหลายแถวเป็นหนึ่งใน MySQL ด้วย CASE WHEN และ GROUP BY

สถานการณ์: Pivot Rows to Columns

ข้อมูลแนวตั้ง (Rows) → แปลงเป็นแนวนอน (Columns) ต่อ Company

ตัวอย่าง: ตาราง demo68

CREATE TABLE demo68 (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    company_name VARCHAR(50),
    employee_name VARCHAR(50),
    country_name VARCHAR(50)
);

INSERT INTO demo68 (company_name, employee_name, country_name) VALUES
('Google', 'John', 'US'),
('Google', 'Bob', 'UK'),
('Google', 'David', 'AUS');

ข้อมูลต้นฉบับ (3 แถว)

+----+--------------+---------------+--------------+
| id | company_name | employee_name | country_name |
+----+--------------+---------------+--------------+
| 1  | Google       | John          | US           |
| 2  | Google       | Bob           | UK           |
| 3  | Google       | David         | AUS          |
+----+--------------+---------------+--------------+

คำสั่ง: รวมเป็น 1 แถวต่อ Company

SELECT 
    company_name,
    MAX(CASE WHEN country_name = 'US'  THEN employee_name END) AS US_Employee_Name,
    MAX(CASE WHEN country_name = 'UK'  THEN employee_name END) AS UK_Employee_Name,
    MAX(CASE WHEN country_name = 'AUS' THEN employee_name END) AS AUS_Employee_Name
FROM demo68
GROUP BY company_name;

ผลลัพธ์ (1 แถว)

+--------------+------------------+------------------+-------------------+
| company_name | US_Employee_Name | UK_Employee_Name | AUS_Employee_Name |
+--------------+------------------+------------------+-------------------+
| Google       | John             | Bob              | David             |
+--------------+------------------+------------------+-------------------+

หลักการทำงาน

  1. CASE WHEN country_name = 'US' THEN employee_name END → คืนชื่อถ้า US, ไม่ใช่ → NULL
  2. MAX(...) → เลือกค่า Non-NULL (เพราะ MAX ข้าม NULL)
  3. GROUP BY company_name → รวมเป็น 1 แถวต่อ Company

วิธีอื่น: GROUP_CONCAT (MySQL Specific)

SELECT 
    company_name,
    GROUP_CONCAT(CASE WHEN country_name = 'US'  THEN employee_name END) AS US_Employee_Name,
    GROUP_CONCAT(CASE WHEN country_name = 'UK'  THEN employee_name END) AS UK_Employee_Name,
    GROUP_CONCAT(CASE WHEN country_name = 'AUS' THEN employee_name END) AS AUS_Employee_Name
FROM demo68
GROUP BY company_name;

ผลลัพธ์: 'John', 'Bob', 'David' (คั่นด้วย Comma) — เหมาะสำหรับหลายค่าต่อกลุ่ม

MySQL 8.0: PIVOT ด้วย Window Function (ไม่มี PIVOT ตรงๆ)

ใช้ ROW_NUMBER() + Conditional Aggregation (เหมือนด้านบน) เป็นมาตรฐาน

กรณีศึกษา: Sales Report by Quarter

SELECT 
    product_id,
    MAX(CASE WHEN quarter = 'Q1' THEN sales END) AS Q1_Sales,
    MAX(CASE WHEN quarter = 'Q2' THEN sales END) AS Q2_Sales,
    MAX(CASE WHEN quarter = 'Q3' THEN sales END) AS Q3_Sales,
    MAX(CASE WHEN quarter = 'Q4' THEN sales END) AS Q4_Sales
FROM sales_data
GROUP BY product_id;

ข้อควรระวัง

  • MAX/MIN ใช้ได้เพราะแต่ละกลุ่มมีค่า Non-NULL เพียง 1 ค่า
  • หากมีหลายค่า (เช่น 2 พนักงานใน US) → MAX จะเลือกค่ามากสุด (Alphabetically)
  • ใช้ GROUP_CONCAT หรือ JSON_ARRAYAGG (MySQL 5.7+) สำหรับหลายค่า