Hỏi Đáp SQL------------ Không có câu hỏi nào là sơ đẳng --------

Những câu hỏi thường gặp khi sử dụng GROUP BY

Một trong những câu hỏi khá phổ biến trên các diễn đàn là Group By.

Hãy xét ví dụ dưới đây.


declare @HoaDon table 
(
id int identity(1,1), 
MaHang int, 
TenHang varchar(100), 
SoTien int, 
TenKH varchar(100), 
NgayBH date 
) 

insert into @HoaDon values
(1,'A',10,'Z','1/1/10'),(2,'W',100,'X','1/2/10'),(2,'W',200,'C','1/1/10'), 
(1,'A',30,'V','1/3/10'),(2,'W',300,'Z','1/2/10'),(2,'W',90,'B','1/1/10'), 
(1,'A',80,'Z','1/4/10'),(3,'E',600,'Z','1/3/10'),(2,'W',160,'X','1/3/10'), 
(1,'A',150,'N','1/5/10'),(3,'E',100,'V','1/4/10'),(3,'E',100,'X','1/1/10') 


select * from @HoaDon 

/* 
id      MaHang      TenHang      SoTien      TenKH      NgayBH 
1      1      A      10      Z      2010-01-01 
2      2      W      100      X      2010-01-02 
3      2      W      200      C      2010-01-01 
4      1      A      30      V      2010-01-03 
5      2      W      300      Z      2010-01-02 
6      2      W      90      B      2010-01-01 
7      1      A      80      Z      2010-01-04 
8      3      E      600      Z      2010-01-03 
9      2      W      160      X      2010-01-03 
10      1      A      150      N      2010-01-05 
11      3      E      100      V      2010-01-04 
12      3      E      100      X      2010-01-01 
*/ 
Yêu cầu thông thường là : tôi muốn có danh sách các mặt hàng và tổng số tiền của mỗi mặt hàng. Yêu cầu này khá đơn giản, qua câu truy xuất:

select 
MaHang, 
SUM(Sotien) TongSoTien 
from @HoaDon 
group by MaHang 

/* 
MaHang      TongSoTien 
1      270 
2      850 
3      800 
*/
Đây là câu truy xuất đơn giản, có lẽ ai cũng biết. Tuy nhiên hầu hết câu hỏi liên quan là : tôi muốn thêm cột khác như TenHang, hay MaKH, hay NgayBH thì làm bằng cách nào?

Vấn đề nảy sinh từ đây, và khá thú vị là mấu chốt là ở phương diện thống kê chứ không phải vấn đề của SQL Server.

- Trên phương diện thống kê, khi muốn biểu thị theo nhóm thì những cột không thuộc nhóm phải được biểu thị qua 1 cách thức tính toán nào đó, như sum ở ví dụ trên. Áp dụng cho câu hỏi trên, bạn sẽ thấy câu hỏi đó không đầy đủ, mà phải có thêm trả lời cho câu hỏi : ứng với mỗi nhóm, cột mà bạn muốn thêm có phải là duy nhất hay không? Nếu không thì trong số những giá trị ấy, bạn muốn lấy giá trị nào (tổng, hay giá trị trung bình hay một cách tính nào đó)?

Khi bạn đã trả lời được cho những câu hỏi này thì vấn đề trở nên đơn giản, cứ theo nguyên tắc trên mà áp dụng cho câu lệnh SQL Server là xong.

- Nếu bạn muốn thêm cột TenHang thì bạn chỉ cần thêm cột TenHang ở Group By và select là xong (giả sử mỗi MaHang chỉ có 1 TenHang và ngược lại).

select 
MaHang, 
TenHang, 
SUM(Sotien) TongSoTien
 from @HoaDon 
group by MaHang,TenHang

- Nếu bạn muốn thêm cột NgayBN (với ngày bán mới nhất) thì cứ thêm vào ở phần select là xong.
select 
MaHang, 
TenHang, 
SUM(Sotien) TongSoTien, 
MAX(NgayBH) NgayBHMoiNhat 
from @HoaDon 
group by MaHang,TenHang 

- Nếu bạn muốn thêm vào cột TenKH thì bạn sẽ thấy yêu cầu của mình không hợp lý trong thống kê vì một khách hàng nào đấy không thể đại diện cho các khách hàng còn lại. Bạn có thể biểu thị tổng số khách hàng cho mỗi nhóm. Trong trường hợp này, bạn cũng làm tương tự, cứ thêm cột count(TenKH) vào select.

select 
MaHang, 
TenHang, 
SUM(Sotien) TongSoTien, 
MAX(NgayBH) NgayBHMoiNhat, 
COUNT(TenKH) TongSoKH 
from @HoaDon 
group by MaHang,TenHang 

/* 
MaHang      TenHang      TongSoTien      NgayBHMoiNhat      TongSoKH 
1      A      270      2010-01-05      4 
3      E      800      2010-01-04      3 
2      W      850      2010-01-03      5 
*/ 
Nếu muốn bỏ qua sự trùng lặp, thêm distinct trong Count.

2 nhận xét:

  1. Chào ad, cho mình hỏi nếu muốn group by theo tháng và năm của một cột ngày cho trước thì làm kiểu gì ạ?mình làm toàn lỗi ạ

    Trả lờiXóa
  2. Ban goi cau lenh va loi len day xem sao

    Trả lờiXóa