Nếu bạn từng thử tính điểm trung bình bài kiểm tra hoặc ví dụ như lương trung bình trong phòng ban, thì bạn đã quen với khái niệm trung bình cộng rồi đấy. Nói thật là cái này học ở trường phổ thông suốt. Trong SQL, bất kỳ bài toán nào liên quan đến tính giá trị trung bình trong một tập dữ liệu đều giải quyết bằng hàm AVG().
Hàm AVG() là một hàm tổng hợp, nó tính trung bình cộng cho một cột số. Nó cộng tất cả giá trị trong cột chỉ định rồi chia cho số lượng giá trị đó. Nó không quan tâm đến NULL (và cái việc bỏ qua này, nghe hơi lạ nhưng lại giúp cuộc sống dễ thở hơn, nói sau nhé).
Cú pháp AVG()
Bắt đầu với cú pháp cơ bản nè:
SELECT AVG(cột)
FROM bảng;
Lưu ý: ở đây cột là cột chứa giá trị số mà bạn muốn tính trung bình.
Ví dụ 1: Lương trung bình của nhân viên
Giả sử mình có bảng employees, lưu thông tin nhân viên và lương của họ:
| id | name | salary |
|---|---|---|
| 1 | Otto | 50000 |
| 2 | Maria | 60000 |
| 3 | Alex | 55000 |
| 4 | Anna | NULL |
| 5 | Dan | 52000 |
Câu truy vấn đơn giản để tính lương trung bình:
SELECT AVG(salary) AS average_salary
FROM employees;
Kết quả:
| average_salary |
|---|
| 54250 |
Nó hoạt động thế nào?
AVG()cộng tất cả lương: 50000 + 60000 + 55000 + 52000 = 217000.- Chia tổng cho số giá trị không phải NULL: 217000 / 4 = 54250.
Đặc điểm của AVG() với NULL
Bạn có thể thấy, khi tính lương trung bình, giá trị NULL trong cột salary bị bỏ qua. Đây là đặc điểm quan trọng của AVG(). Nó chỉ tính giá trị không phải NULL thôi.
Thử ví dụ này nhé:
SELECT AVG(NULL) AS result;
Kết quả:
| result |
|---|
| NULL |
Điều này lại xác nhận AVG() bỏ qua NULL. Nhưng nếu cả tập dữ liệu đều là NULL, kết quả sẽ là NULL.
Nhưng nếu trong bảng không phải là NULL mà là 0, thì kết quả đó không bị bỏ qua đâu nha.
Bảng employees
| id | salary |
|---|---|
| 1 | 1000 |
| 2 | 0 |
| 3 | NULL |
| 4 | 2000 |
Câu truy vấn SQL:
SELECT AVG(salary) AS avg_salary
FROM employees;
Kết quả:
| avg_salary |
|---|
| 1000 |
Tại sao lại vậy?
Bởi vì AVG() sẽ tính:
[(1000 + 0 + 2000) / 3 = 1000]
Dòng có NULL bị bỏ qua khi tính trung bình.
Ví dụ: Tính tuổi trung bình của sinh viên
Giờ chuyển sang bảng students nhé:
| id | name | age |
|---|---|---|
| 1 | Anna | 20 |
| 2 | Max | 22 |
| 3 | Maria | NULL |
| 4 | Otto | 21 |
Truy vấn:
SELECT AVG(age) AS average_age
FROM students;
Kết quả:
| average_age |
|---|
| 21 |
AVG()bỏ qua bạn Maria vì tuổi của bạn ấy là NULL.- Giá trị trung bình được tính là: (20 + 22 + 21) / 3 = 21.
Làm tròn kết quả
Đôi khi kết quả AVG() trả về số thập phân với nhiều chữ số sau dấu phẩy.
Nếu bạn muốn lấy số đã làm tròn, có thể dùng hàm ROUND().
Bảng employees
| id | salary |
|---|---|
| 1 | 50000 |
| 2 | 60000 |
| 3 | 47000 |
| 4 | NULL |
Truy vấn SQL
SELECT ROUND(AVG(salary), 2) AS rounded_average_salary
FROM employees;
Kết quả
| rounded_average_salary |
|---|
| 52333.33 |
Dòng có NULL bị loại khỏi phép tính, nên trung bình chỉ tính trên ba giá trị thôi.
Lọc dữ liệu trước khi tính AVG()
Nếu bạn muốn tính trung bình nhưng chỉ cho các giá trị thỏa mãn điều kiện nào đó, hãy dùng WHERE.
Bảng employees
| id | salary |
|---|---|
| 1 | 50000 |
| 2 | 60000 |
| 3 | 47000 |
| 4 | 60000 |
| 5 | NULL |
Ví dụ: Tìm lương trung bình của nhân viên có id > 2.
SELECT AVG(salary) AS average_salary
FROM employees
WHERE id > 2;
Kết quả
| average_salary |
|---|
| 53500 |
Chỉ các lương có id = 3 và id = 4 được tính. Dòng có NULL bị loại.
Ví dụ: Truy vấn phức tạp với AVG()
Có thể kết hợp hàm AVG() với các hàm tổng hợp và toán tử khác.
Giả sử mình có bảng bán hàng sales:
| sale_id | product | quantity | price |
|---|---|---|---|
| 1 | Điện thoại | 2 | 500 |
| 2 | Laptop | 1 | 1500 |
| 3 | Máy tính bảng | 3 | 300 |
Truy vấn để tính trung bình tổng số tiền bán:
SELECT AVG(quantity * price) AS average_total_sale
FROM sales;
Kết quả:
| averagetotalsale |
|---|
| 950 |
Mẹo thực tế và lỗi thường gặp
Làm việc với AVG() nên cẩn thận để tránh lỗi phổ biến:
Giá trị NULL: đôi khi bạn sẽ bất ngờ vì kết quả nhỏ hơn mong đợi. Nhớ là AVG() bỏ qua dòng có NULL.
Trộn kiểu dữ liệu: nếu trong cột vừa có số vừa có text (cái này thực ra là thói quen xấu), AVG() sẽ báo lỗi luôn.
GO TO FULL VERSION