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

ป้องกัน GROUP BY รวมค่า NULL เป็นกลุ่มเดียวใน MySQL ด้วย IFNULL

ปัญหา: GROUP BY รวม NULL ทั้งหมดเป็นกลุ่มเดียว

พฤติกรรมมาตรฐานของ SQL: GROUP BY column จะรวมค่า NULL ทั้งหมดเป็นกลุ่มเดียว เพราะ NULL = NULL เป็น UNKNOWN (ไม่ใช่ TRUE) แต่ GROUP BY จัดว่า "เท่ากัน" สำหรับการจัดกลุ่ม

สร้างตารางและข้อมูล (มี NULL 2 แถว)

mysql> CREATE TABLE DemoTable1511 (
    -> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> FirstName VARCHAR(20)
    -> );
Query OK, 0 rows affected (1.97 sec)

mysql> INSERT INTO DemoTable1511(FirstName) VALUES
    -> ('John'), ('Robert'), ('Mike'), ('Robert'), (NULL), (NULL), ('Mike');
Query OK, 7 rows affected

ข้อมูลทั้งหมด

+----+-----------+
| Id | FirstName |
+----+-----------+
|  1 | John      |
|  2 | Robert    |
|  3 | Mike      |
|  4 | Robert    |
|  5 | NULL      |
|  6 | NULL      |
|  7 | Mike      |
+----+-----------+

GROUP BY ปกติ: NULL รวมเป็น 1 กลุ่ม

mysql> SELECT MIN(Id) AS Id, FirstName FROM DemoTable1511 GROUP BY FirstName ORDER BY Id;
+------+-----------+
| Id   | FirstName |
+------+-----------+
|    1 | John      |
|    2 | Robert    |
|    3 | Mike      |
|    5 | NULL      |  <-- NULL 2 แถวรวมเป็น 1
+------+-----------+

วิธีแก้: ใช้ IFNULL(FirstName, Id) ใน GROUP BY

mysql> SELECT MIN(Id) AS Id, FirstName 
    -> FROM DemoTable1511 
    -> GROUP BY FirstName, IFNULL(FirstName, Id) 
    -> ORDER BY Id;

ผลลัพธ์: NULL แยกเป็น 2 กลุ่ม (Id 5 และ 6)

+------+-----------+
| Id   | FirstName |
+------+-----------+
|    1 | John      |
|    2 | Robert    |
|    3 | Mike      |
|    5 | NULL      |
|    6 | NULL      |
+------+-----------+

คำอธิบาย IFNULL(FirstName, Id)

  • ถ้า FirstName IS NOT NULL → คืน FirstName → จัดกลุ่มตามชื่อปกติ
  • ถ้า FirstName IS NULL → คืน Id (Unique) → แต่ละ NULL ได้ค่า Id ต่างกัน → แยกกลุ่ม

วิธีอื่น: ใช้ CONCAT กับ PK

GROUP BY CONCAT(FirstName, '#', Id)
-- หรือ
GROUP BY COALESCE(FirstName, CONCAT('NULL_', Id))

⚠️ ข้อควรระวัง

  • วิธีนี้ทำให้ NULL ไม่ถูกรวมกลุ่ม แต่ เปลี่ยน Semantics ของ GROUP BY (แต่ละ NULL กลายเป็นกลุ่มตัวเอง)
  • ใช้เฉพาะเมื่อต้องการ "แยกแถว NULL" จริงๆ (เช่น Audit Log, Raw Data)
  • ปกติแล้ว NULL ควรเป็นกลุ่มเดียวกัน (Standard SQL Behavior)

MySQL 8.0: ใช้ GROUPING SETS / ROLLUP (Advanced)

SELECT FirstName, COUNT(*) 
FROM DemoTable1511 
GROUP BY ROLLUP(FirstName);  -- รวม Total row ด้วย