TM Data School – Giả sử bạn có một bảng chứa dữ liệu chi tiêu của các khách hàng, về lịch sử checkout và giá trị của mỗi đơn hàng của một cửa hàng bách hóa trực tuyến. Với những dữ liệu này, bạn muốn ứng dụng RFM và thực hiện các phép tính để tìm ra mốc chi tiêu hợp lý, nhằm phân nhóm khách hàng theo mức độ chi tiêu trong năm thành 3 tệp: nhóm khách hàng mua một lần, nhóm khách hàng quay lại và nhóm khách hàng trung thành. Câu lệnh GROUP BY kết hợp HAVING trong SQL sẽ giúp bạn tìm ra đáp án cho bài toán này.
Vậy GROUP BY và HAVING là gì, cách dùng như nào? Cùng TM tìm hiểu câu trả lời trong bài viết sau nhé!
1. GROUP BY là gì? Syntax như nào? Ví dụ?
GROUP BY là gì?
Mệnh đề GROUP BY được dùng để nhóm các dòng dữ liệu theo một hoặc nhiều đối tượng. GROUP BY thường được dùng với các hàm tổng hợp như COUNT(), MAX(), MIN(), SUM(), AVG()) để tính toán các giá trị theo một nhóm.
GROUP BY giúp “gom nhóm” dữ liệu và thực hiện các phép toán tổng hợp
Syntax của GROUP BY
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
GROUP BY thực hiện theo thứ tự:
- Chia nhóm: tập dữ liệu được chia thành các hàng theo một hoặc nhiều đối tượng
- Thực hiện các phép tổng hợp: ví dụ tính giá trị trung bình/lấy giá trị nhỏ nhất/lớn nhất và trả về một giá trị duy nhất của nhóm đối tượng đó
- Trả về kết quả theo nhóm: Tất cả các kết quả đầu ra này được kết hợp trong một bảng duy nhất.
Ví dụ sử dụng GROUP BY:
GROUP BY theo một cột
Với câu hỏi ở lời mở đầu, giả sử có bảng Order chứa các trường dữ liệu customer_id (id của khách hàng), order_id (id của đơn hàng), order_created_at (thời điểm thanh toán đơn hàng), GMV (tổng giá trị đơn hàng), có thể thực hiện truy vấn dưới đây để tính ra tổng GMV của mỗi khách hàng trong một năm qua:
SELECT
customer_id,
SUM(gmv) AS total_gmv
FROM Order
WHERE order_created_at >= getdate() – interval ‘1 year’
GROUP BY 1
Sau khi tính toán và xác định mức phân bổ của tổng GMV của mỗi khách hàng, chúng ta lựa chọn 2 mốc để phân nhóm: khách hàng có tổng GMV dưới 100$ là khách hàng mua một lần, tổng GMV từ 100$ tới dưới 5000$ là khách hàng mua nhiều lần, trong khi trên 5000$ là khách hàng trung thành.
Kết hợp HAVING, chúng ta có thể biết những khách hàng nào là khách hàng trung thành:
SELECT
customer_id,
SUM(gmv) AS total_gmv
FROM Order
WHERE order_created_at >= getdate() – interval ‘1 year’
GROUP BY 1
HAVING SUM(gmv) >= 5000
Một ví dụ khác:
Giả sử, có bảng dữ liệu Employee chứa dữ liệu cá nhân của các nhân viên, bao gồm id, tên, mức lương và tuổi:
CREATE TABLE emp (
emp_no INT PRIMARY KEY,
name VARCHAR(50),
sal DECIMAL(10,2),
age INT
);
GROUP BY theo tên của nhân viên và tính tổng lương sẽ trả lời câu hỏi: “Tất cả nhân viên có tên là a có tổng mức lương là bao nhiêu?”
SELECT NAME, SUM(SALARY) FROM emp
GROUP BY NAME;
Kết quả trả về:
Các hàng có giá trị ở cột name sẽ được nhóm lại thành một, trong khi cột SUM(sal) sẽ tính tổng tất cả giá trị sal của nhân viên có tên tương ứng.
GROUP BY theo nhiều cột
Giả sử, có một bảng dữ liệu Student với các trường dữ liệu của mỗi học sinh khi tham gia một môn học trong một năm.
CREATE TABLE student (
name VARCHAR(50),
year INT,
subject VARCHAR(50)
);
GROUP BY theo môn học và năm học và đếm số học sinh tham gia lớp sẽ trả lời câu hỏi: “Trong năm học a, có bao nhiêu học sinh tham gia môn học b?”
SELECT SUBJECT, YEAR, Count(*)
FROM Student
GROUP BY SUBJECT, YEAR;
Số học sinh tham gia cùng một môn học trong cùng một năm học sẽ được tính là một nhóm, trong khi những học sinh tham gia môn học khác trong cùng một năm học sẽ được nhóm vào nhóm khác.
Một số ví dụ khác sử dụng GROUP BY – Slide khóa học SQL for Data Analysis
2. HAVING là gì? Syntax như nào? Ví dụ?
HAVING là gì?
Câu lệnh WHERE được dùng để đặt điều kiện cho các bản ghi, nhưng nếu chúng ta muốn đặt điều kiện cho các nhóm thì sao? Câu lệnh HAVING được dùng cho tình huống này.
HAVING sẽ đặt điều kiện cho các trường tổng hợp sau khi thực hiện gom nhóm với GROUP BY. Như vậy, khác với WHERE, HAVING có thể sử dụng kết hợp với các hàm tổng hợp như SUM(), COUNT(),…,
HAVING khác gì với WHERE?
HAVING | WHERE |
HAVING kiểm tra điều kiện theo một nhóm | WHERE kiểm tra điều kiện theo từng dòng |
HAVING có thể sử dụng kết hợp với các hàm tổng hợp | WHERE không thể sử dụng kết hợp với các hàm tổng hợp |
HAVING được thực hiện sau khi gom nhóm, vì vậy HAVING đứng sau GROUP BY | WHERE được thực hiện trước khi gom nhóm, vì vậy WHERE đứng trước GROUP BY |
Syntax của HAVING:
SELECT column1, function_name(column2)
FROM table_name
WHERE condition
GROUP BY column1, column2
HAVING condition
ORDER BY column1, column2;
Trong đó:
- function_name: Các hàm tổng hợp, ví dụ như SUM() , AVG().
- table_name: Tên bảng cần truy xuất dữ liệu
- condition: Logic của điều kiện
Ví dụ sử dụng HAVING:
SELECT NAME, SUM(sal) FROM Emp
GROUP BY name
HAVING SUM(sal)>3000;
Truy vấn này sẽ thực hiện theo từng bước: tính tổng lương của từng nhóm nhân viên có cùng tên, sau đó giới hạn chỉ trả về những nhóm có tổng mức lương lớn hơn 3000.
Các ví dụ khác có thể sử dụng HAVING – Slide khóa học SQL for Data Analysis
Lưu ý thứ tự thực hiện các mệnh đề:
Thứ tự thực hiện các mệnh đề lần lượt là:
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
- LIMIT
Giải thích:
- FROM xác định bảng dữ liệu được truy xuất
- WHERE lọc dữ liệu của bảng theo điều kiện nhất định
- GROUP BY nhóm các dòng theo từng nhóm
- HAVING lọc điều kiện theo từng nhóm
- SELECT lựa chọn các trường dữ liệu sẽ hiển thị ở kết quả
- ORDER BY sắp xếp kết quả hiển thị theo một hoặc nhiều cột, theo thứ tự bảng chữ cái/giảm dần – tăng dần
- LIMIT giới hạn số lượng bản ghi hiển thị từ kết quả truy vấn.
Đây là cấu trúc của một truy vấn SQL cơ bản, nhằm mục đích truy xuất và thao tác với dữ liệu của một bảng trong cơ sở dữ liệu.
Như vậy, bộ xử lý truy vấn không bắt đầu từ SELECT mà bắt đầu bằng cách giới hạn dữ liệu và thực hiện các phép tính toán trước khi trả về với SELECT.
Thứ tự này giải thích tại sao:
- HAVING không cho phép sử dụng ALIAS, trong khi ORDER BY lại được sử dụng
- HAVING được sử dụng cùng với GROUP BY để áp dụng các điều kiện trên dữ liệu tổng hợp, trong khi WHERE thì không thể
- LIMIT chưa chắc đã là phương án tối ưu nhất bởi mệnh đề này sẽ chỉ giới hạn số lượng bản ghi trả về trong khi bộ xử lý truy vấn vẫn phải thực hiện tất cả các bước
Tạm kết
Biết những câu lệnh truy vấn và xử lý dữ liệu cơ bản nhất của SQL chính là bước đi đầu tiên, nhưng làm thế nào để kết hợp và vận dụng linh hoạt cho những bài toán phức tạp thì thật không đơn giản. Bạn không chỉ cần tư duy logic, nắm được ý nghĩa của các trường & các bảng dữ liệu mà còn cần phải nắm được loại dữ liệu, vị trí lưu trữ cũng như liên tục trau dồi SQL thông qua các case study khác nhau.
Đây cũng là một trong những nội dung quan trọng được truyền tải trong khóa Data System của Tomorrow Marketers. Với 2 học phần, khóa học sẽ giúp bạn:
- Nắm vững tư duy thiết lập thế thống dữ liệu, hiểu cách dữ liệu được tổ chức và lưu trữ, từ đó biết cách trích xuất và xử lý dữ liệu hiệu quả với mỗi một bài toán khác nhau của doanh nghiệp
- Cung cấp các “câu lệnh” SQL từ đơn giản đến nâng cao để bạn có thể chủ động thực hiện các truy vấn nhằm tìm kiếm thông tin, biến đổi dữ liệu để phục vụ cho việc tạo báo cáo phân tích.
Tìm hiểu thêm về khóa học SQL for Data Analysis:
Bài viết được biên dịch từ learnsql.com, xin vui lòng không sao chép dưới mọi hình thức!