Để lấy tổng số hàng của một truy vấn và hiển thị cùng với từng hàng kết quả, sử dụng truy vấn con (subquery) với COUNT(*).
Tạo bảng sinh viên
mysql> CREATE TABLE DemoTable (
-> StudentId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentFirstName VARCHAR(20),
-> StudentAge INT
-> );
Chèn 10 bản ghi mẫu
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('John', 23);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Larry', 21);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Johnny', 23);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Chris', 21);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('David', 23);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('James', 21);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Jace', 24);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Mike', 21);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Robert', 25);
mysql> INSERT INTO DemoTable(StudentFirstName, StudentAge) VALUES('Mike', 22);
Truy vấn lấy tổng số hàng cho mỗi bản ghi
mysql> SELECT StudentFirstName,
-> (SELECT COUNT(*) FROM DemoTable) AS Total_Count
-> FROM DemoTable LIMIT 10;
+------------------+-------------+ | StudentFirstName | Total_Count | +------------------+-------------+ | John | 10 | | Larry | 10 | | Johnny | 10 | | Chris | 10 | | David | 10 | | James | 10 | | Jace | 10 | | Mike | 10 | | Robert | 10 | | Mike | 10 | +------------------+-------------+
Phân tích hiệu năng
- Ưu điểm: Đơn giản, dễ hiểu, tổng số hàng được tính một lần cho toàn bộ truy vấn
- Nhược điểm: Subquery thực thi cho mỗi hàng (tùy optimizer), có thể chậm trên bảng lớn
Các phương án thay thế hiệu quả hơn
1. Biến người dùng (User-defined variable)
SELECT @total := COUNT(*) FROM DemoTable; SELECT StudentFirstName, @total AS Total_Count FROM DemoTable;
2. CTE (MySQL 8.0+)
WITH Total AS (SELECT COUNT(*) AS cnt FROM DemoTable) SELECT StudentFirstName, Total.cnt AS Total_Count FROM DemoTable, Total;
3. SQL_CALC_FOUND_ROWS (đã deprecated MySQL 8.0.17+)
SELECT SQL_CALC_FOUND_ROWS StudentFirstName FROM DemoTable LIMIT 10; SELECT FOUND_ROWS();
Khuyến nghị
Với bảng lớn, hãy dùng CTE hoặc biến người dùng. Tránh SQL_CALC_FOUND_ROWS vì đã bị loại bỏ.