Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Ngăn GROUP BY gom các giá trị NULL thành một hàng trong MySQL

Mặc định, MySQL coi **tất cả giá trị NULL là bằng nhau** và gom thành **một nhóm duy nhất** khi dùng GROUP BY. Để tách từng hàng NULL thành nhóm riêng biệt, hãy thêm biểu thức phân biệt vào GROUP BY.

Kỹ thuật: GROUP BY cot, IFNULL(cot, cot_khac)

Sử dụng IFNULL(cot, Id) – với hàng NULL, dùng Id (duy nhất) làm khóa phụ để tách nhóm.

Ví dụ minh họa

Tạo bảng có FirstName chứa NULL:

mysql> CREATE TABLE DemoTable1511 (
    -> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> FirstName VARCHAR(20)
    -> );
mysql> INSERT INTO DemoTable1511(FirstName) VALUES
    -> ('John'), ('Robert'), ('Mike'), ('Robert'), (NULL), (NULL), ('Mike');

GROUP BY thông thường (gom 2 NULL thành 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      |  -- 2 hàng NULL gộp thành 1
+------+-----------+

GROUP BY với IFNULL(FirstName, Id) (tách riêng từng NULL):

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

Kết quả – 2 hàng NULL tách biệt:

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

Giải thích

  • Với hàng không NULL: IFNULL(FirstName, Id) = FirstName → nhóm theo tên.
  • Với hàng NULL: IFNULL(NULL, Id) = Id (duy nhất) → mỗi hàng NULL thành nhóm riêng.
  • MIN(Id) lấy ID nhỏ nhất trong nhóm (đại diện).

Cách khác (MySQL 8.0+)

Dùng GROUPING SETS hoặc window function ROW_NUMBER() OVER (PARTITION BY FirstName ORDER BY Id) để đánh số thứ tự trong nhóm, sau đó lọc.

⚠️ Lưu ý

  • Kỹ thuật này chỉ tác động đến **hiển thị/phân nhóm** – không thay đổi dữ liệu gốc.
  • Cần cột duy nhất (như PK) để làm khóa phân biệt cho NULL.