Mục lục
Định nghĩa Window Functions và GROUP BY
GROUP BY
Mệnh đề GROUP BY cho phép nhóm một tập hợp các hàng dựa trên một số tiêu chí và áp dụng một hàm tổng hợp (aggregate function) (ví dụ: MIN, AVG, …) cho mỗi nhóm, thu được một kết quả cho mỗi nhóm bản ghi.- Cú pháp
SELECT column1, Aggregate Functions(column2) FROM table_name WHERE [condition] GROUP BY column1
Window Function
Window Function (hay Analytics Function) là hàm mà tính toán các giá trị trên một nhóm hàng và trả về một kết quả cho mỗi hàng.- Cú pháp
analytic_function_name ( [ argument_list ] ) OVER over_clause Trong đó: over_clause: { named_window | ( [ window_specification ] ) } window_specification: [ named_window ] [ PARTITION BY partition_expression [, ...] ] [ ORDER BY expression [ { ASC | DESC } ] [, ...] ] [ window_frame_clause ] window_frame_clause: { rows_range } { frame_start | frame_between } rows_range: { ROWS | RANGE }Cú pháp thông thường:
analytic_function_name ( [ argument_list ] ) over ([ PARTITION BY partition_expression [, ...] ] [ ORDER BY expression [ { ASC | DESC } ] [, ...] ])
Sự khác biệt giữa Window Functions và GROUP BY
Để so sánh sự khác nhau giữa Window Functions và GROUP BY, ta có ví dụ minh hoạ như sauBài toán: Từ bảng FactInternetSales và DimSalesTerritory,– Tính tổng doanh thu bán qua Internet của từng nhóm lãnh thổ (SalesTerritoryGroup)– Tính tỷ lệ đóng góp của từng khu vực (SalesTerritoryRegion) trong mỗi nhóm lãnh thổ đó.Với yêu cầu đầu tiên, ta có thể thực hiện bằng aggregate function và GROUP BY như sau:SELECT dst.SalesTerritoryGroup , SUM(fis.SalesAmount) AS SalesByGroup FROM FactInternetSales AS fis LEFT JOIN DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryGroupKết quả trả về gồm 3 dòng:

SELECT dst.SalesTerritoryGroup , SUM(fis.SalesAmount) OVER (PARTITION BY dst.SalesTerritoryGroup) AS SalesByGroup FROM FactInternetSales AS fis LEFT JOIN DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKeyKết quả trả về 60398 dòng như sau:




SELECT ct2.* , ct1.SalesByGroup , FORMAT(ct2.SalesByRegion/ct1.SalesByGroup, 'p') AS Contribution FROM ( SELECT dst.SalesTerritoryGroup , SUM(fis.SalesAmount) AS SalesByGroup FROM FactInternetSales AS fis LEFT JOIN DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryGroup ) AS ct1 JOIN ( SELECT dst.SalesTerritoryRegion , dst.SalesTerritoryGroup , SUM(fis.SalesAmount) AS SalesByRegion FROM FactInternetSales AS fis JOIN DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryRegion , dst.SalesTerritoryGroup ) AS ct2 ON ct1.SalesTerritoryGroup = ct2.SalesTerritoryGroupVới Window Function, đầu tiên ta viết một subquery hoặc CTE để tạo ra bảng tính doanh thu theo khu vực, mục đích để tính toán cuối cùng thực hiện trên bảng đó.
WITH cte AS ( SELECT dst.SalesTerritoryRegion , dst.SalesTerritoryGroup , SUM(fis.SalesAmount) AS SalesByRegion FROM FactInternetSales AS fis join DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryRegion , dst.SalesTerritoryGroup ) SELECT SalesTerritoryRegion , SalesTerritoryGroup , SalesByRegion ,SUM(cte.SalesByRegion) OVER (PARTITION BY SalesTerritoryGroup) AS SalesByGroup , FORMAT(SalesByRegion/SUM(cte.SalesByRegion) OVER (PARTITION BY SalesTerritoryGroup), 'p') AS Contribution FROM cteCả Window Functions và GROUP BY cho ra cùng một kết quả gồm 10 dòng như sau:

Kết luận
Window Functions và GROUP BY có các điểm khác biệt như sau:- Window Function tính toán giá trị cho từng dòng, trong khi GROUP BY thì không.
- GROUP BY làm giảm số dòng ban đầu xuống bằng đúng số nhóm, Window Function thì giữ nguyên số dòng.
- Vì tính chất trên, có thể dùng Window Function thể thêm tính toán phân theo nhóm vào bảng ban đầu trong khi nếu dùng GROUP BY thì cần các cách xử lý khác, chẳng hạn như JOIN.
DP-080: Querying Data with Microsoft T-SQL