Để lấy danh sách giá trị duy nhất (DISTINCT) kèm theo số lần xuất hiện của mỗi giá trị, bạn dùng GROUP BY kết hợp hàm tập hợp COUNT(*).
Cú pháp
SELECT ten_cot, COUNT(*) AS so_lan_xuat_hien
FROM ten_bang
GROUP BY ten_cot;
Ví dụ minh họa
1. Tạo bảng
CREATE TABLE selectDistinct_CountDemo (
Id INT NOT NULL AUTO_INCREMENT,
Name VARCHAR(10),
AppearanceId INT,
PRIMARY KEY(Id)
);
2. Chèn dữ liệu (Larry xuất hiện 4 lần)
INSERT INTO selectDistinct_CountDemo(Name, AppearanceId) VALUES
('Larry', 1), ('John', 2), ('Larry', 3),
('Larry', 10), ('Carol', 11), ('Larry', 15);
3. Xem dữ liệu gốc
SELECT * FROM selectDistinct_CountDemo;
Kết quả:
+----+-------+--------------+
| Id | Name | AppearanceId |
+----+-------+--------------+
| 1 | Larry | 1 |
| 2 | John | 2 |
| 3 | Larry | 3 |
| 4 | Larry | 10 |
| 5 | Carol | 11 |
| 6 | Larry | 15 |
+----+-------+--------------+
4. Truy vấn: DISTINCT + COUNT
SELECT Name, COUNT(*) AS TotalAppearance
FROM selectDistinct_CountDemo
GROUP BY Name;
Kết quả:
+-------+-----------------+
| Name | TotalAppearance |
+-------+-----------------+
| Larry | 4 |
| John | 1 |
| Carol | 1 |
+-------+-----------------+
Các biến thể hữu ích
1. Sắp xếp theo số lần giảm dần
SELECT Name, COUNT(*) AS cnt
FROM selectDistinct_CountDemo
GROUP BY Name
ORDER BY cnt DESC;
2. Chỉ lấy giá trị xuất hiện > 1 lần (trùng lặp)
SELECT Name, COUNT(*) AS cnt
FROM selectDistinct_CountDemo
GROUP BY Name
HAVING COUNT(*) > 1;
3. Đếm DISTINCT trên cột khác (ví dụ: số AppearanceId riêng biệt per Name)
SELECT Name, COUNT(DISTINCT AppearanceId) AS unique_appearances
FROM selectDistinct_CountDemo
GROUP BY Name;
4. Nhóm theo nhiều cột
SELECT Name, Age, COUNT(*)
FROM bang
GROUP BY Name, Age;
⚠️ Sai lầm thường gặp
Sai: DISTINCT + COUNT(*) không cần GROUP BY
-- KHÔNG HỢP LỆ trong hầu hết SQL (MySQL ONLY_FULL_GROUP_BY sẽ báo lỗi)
SELECT DISTINCT Name, COUNT(*) FROM bang;
Đúng: GROUP BY
SELECT Name, COUNT(*) FROM bang GROUP BY Name;
Hiệu năng & Index
- Tạo index trên cột GROUP BY:
CREATE INDEX idx_name ON bang(Name); COUNT(*)đếm tất cả hàng (kể NULL)COUNT(cot)chỉ đếm hàng có cot NOT NULLCOUNT(DISTINCT cot)đếm giá trị duy nhất (chậm hơn, cần sort/hash)
Mở rộng: Window Function (MySQL 8.0+)
SELECT DISTINCT Name,
COUNT(*) OVER (PARTITION BY Name) AS TotalAppearance
FROM selectDistinct_CountDemo;
Trả về cùng số hàng như bảng gốc nhưng có cột count cho mỗi nhóm.