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

Lấy dòng với GROUP BY trong MySQL?

Giải pháp: GROUP BY với hàm tổng hợp

GROUP BY gom nhóm các dòng có cùng giá trị, kết hợp hàm tổng hợp (SUM, COUNT, AVG, MAX, MIN) để tính toán mỗi nhóm.

Ví dụ minh họa

Tạo bảng sản phẩm

mysql> CREATE TABLE DemoTable (
    Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Subject VARCHAR(20),
    Price INT
);

mysql> INSERT INTO DemoTable(Subject, Price) VALUES('MySQL', 456), ('MySQL', 456), ('MongoDB', 56), ('MongoDB', 60), ('Java', 100), ('Java', 130);

Dữ liệu gốc

+----+---------+-------+
| Id | Subject | Price |
+----+---------+-------+
| 1  | MySQL   | 456   |
| 2  | MySQL   | 456   |
| 3  | MongoDB | 56    |
| 4  | MongoDB | 60    |
| 5  | Java    | 100   |
| 6  | Java    | 130   |
+----+---------+-------+

Truy vấn GROUP BY

mysql> SELECT SUM(Price) AS Total, Subject 
    -> FROM DemoTable 
    -> GROUP BY Subject;

Kết quả

+-------+---------+
| Total | Subject |
+-------+---------+
| 912   | MySQL   |
| 116   | MongoDB |
| 230   | Java    |
+-------+---------+

Các hàm tổng hợp phổ biến

HàmÝ nghĩaVí dụ
COUNT(*)Số dòngCOUNT(*)
SUM(col)TổngSUM(Price)
AVG(col)Trung bìnhAVG(Price)
MIN(col)Nhỏ nhấtMIN(Price)
MAX(col)Lớn nhấtMAX(Price)
GROUP_CONCAT(col)Nối chuỗiGROUP_CONCAT(Subject)
STDDEV(col)Độ lệch chuẩnSTDDEV(Price)

GROUP BY nhiều cột

SELECT Subject, YEAR(created_at) AS year, SUM(Price) 
FROM DemoTable 
GROUP BY Subject, YEAR(created_at);

⚠️ Quy tắc ONLY_FULL_GROUP_BY (MySQL 5.7+)

Mặc định bật. Mọi cột trong SELECT phải:

  1. Có trong GROUP BY, HOẶC
  2. Trong hàm tổng hợp
-- Sai (nếu ONLY_FULL_GROUP_BY=ON)
SELECT Subject, Price FROM DemoTable GROUP BY Subject;
-- Error: 'Price' isn't in GROUP BY

-- Đúng
SELECT Subject, SUM(Price) FROM DemoTable GROUP BY Subject;
SELECT Subject, ANY_VALUE(Price) FROM DemoTable GROUP BY Subject;  -- Lấy bất kỳ giá trị

HAVING vs WHERE

-- WHERE: Lọc TRƯỚC khi gom nhóm
WHERE Price > 100

-- HAVING: Lọc SAU khi gom nhóm
HAVING SUM(Price) > 500

Ứng dụng thực tế

-- Doanh thu theo danh mục
SELECT category, SUM(amount) AS revenue, COUNT(*) AS orders
FROM orders
GROUP BY category
ORDER BY revenue DESC;

-- User hoạt động
SELECT user_id, COUNT(*) AS actions, MAX(created_at) AS last_active
FROM logs
GROUP BY user_id
HAVING COUNT(*) > 10;