MySQL8.0窗口函数
开窗函数(Window Functions)在MySQL 8.0中得到了支持,这为执行复杂查询提供了极大的便利。开窗函数允许你对一组行的集合(即窗口)执行聚合计算,而不需要将这些行分组(GROUP BY),这样可以保留明细数据的同时进行复杂的分析。
常用开窗函数
- ROW_NUMBER():为结果集中的每一行分配一个唯一的行号,从1开始。
- RANK():根据ORDER BY子句排序的结果,为结果集中的每一行分配一个排名。如果存在相同值,则跳过后续排名。
- DENSE_RANK():与RANK()类似,但如果存在相同值,不会跳过后续排名。
- NTILE(n):将分区或结果集划分为n个桶,并为每一行分配一个桶编号。
- SUM(), AVG(), MIN(), MAX()等聚合函数:可以在不使用GROUP BY的情况下计算聚合值。
使用示例
假设有一个名为sales
的表,包含id
, name
, amount
三个字段,想要按amount
降序排列并为每条记录添加排名:
SELECT
id, name, amount,
ROW_NUMBER() OVER (ORDER BY amount DESC) AS 'RowNum',
RANK() OVER (ORDER BY amount DESC) AS 'Rank',
DENSE_RANK() OVER (ORDER BY amount DESC) AS 'DenseRank'
FROM sales;
在这个例子中,我们使用了ROW_NUMBER()
, RANK()
, 和 DENSE_RANK()
这三个开窗函数来展示不同类型的排名方式。
另外,开窗函数还可以结合PARTITION BY
子句使用,以实现基于特定列值的分区统计。例如,如果你想在上面的例子中按照销售人员(假设name
表示销售人员)来分别计算他们的销售额排名,可以这样做:
SELECT
id, name, amount,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY amount DESC) AS 'SalesRankPerPerson'
FROM sales;
这将为每个销售人员单独计算其销售额的排名。开窗函数极大地增强了SQL的功能,使得处理复杂的数据分析任务变得更加简单直接。
其它例子
SELECT
aad.record_date,
aad.user_id,
aad.`type`,
aac.full_category_name AS category_name,
aad.amount,
aad.remark,
SUM(aad.amount) OVER (PARTITION BY aad.record_date) AS total_daily_amount -- 使用窗口函数计算每天的总金额
FROM
aias_accounting_detail aad
LEFT JOIN
aias_accounting_category aac
ON
aad.category_id = aac.id
ORDER BY
aad.record_date DESC;