INSERT INTO Employees (Name, DepartmentID, Salary) VALUES('css',1,45000);
select *,
rank() over (partition by DepartmentID order by Salary desc ) total
from employees;
dense_rank()函数:
复制代码
select *,
dense_rank() over (partition by DepartmentID order by Salary desc ) total
from employees;
select *,
last_value(Salary) over (partition by DepartmentID order by Salary desc
rows between unbounded preceding and unbounded following ) total
from employees;
解释一下设置小窗口的含义:rows between unbounded preceding and unbounded following
之前所有的行到之后所有的行,那么让我们输出一下。
我们可以很清晰的看出来,输出的是每一组里面最后一个的薪资。
2.窗口函数语法解释-OVER [PARTITION BY <...>]
over是窗口函数的标志,partition by 用来指定分组,把partition by 后面跟的字段相同的放在一起
3.窗口函数语法解释-[ORDER BY <...>]
用于指定每个分组内的数据排序规则 支持____ASC、DESC, 跟group by 中的order by是一样的用法
4.窗口函数语法解释-[window_expression]
用于指定每个窗口中 操作的数据范围 默认是窗口中所有行
窗口子句操作的数据范围: 1)起始行:N preceding/unbounded preceding
2)当前行:currentrow
3)终止行:N following/unbounded following
举例: rows between unbounded preceding and current row 从之前所有的行到当前行
rows between 2 preceding and current row 从前面两行到当前行
rows between current row and unbounded following 从当前行到之后所有的行
rows between current row and 1following 从当前行到后面一行
注意:
排序子句后面缺少窗口子句,窗口规范默认是rows between unbounded preceding and current row
排序子句和窗口子句都缺失,窗口规范默认是 rows between unbounded preceding and unbounded following
总体流程
1)通过partition by和 order by 子句确定大窗口(定义出上界unbounded preceding和下界unbounded following)
2)通过row 子句针对每一行数据确定小窗口(滑动窗口)
3)对每行的小窗口内的数据执行函数并生成新的列
窗口函数练习
建库建表语句:
复制代码
CREATE DATABASE IF NOT EXISTS sales_db;
USE sales_db;
CREATE TABLE IF NOT EXISTS sales (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT comment '商品id',
sale_date DATE comment '销售日期',
amount DECIMAL(10, 2)comment '销售额',
region VARCHAR(50) comment '地区'
)comment '销售';
-- 插入一些示例数据
INSERT INTO sales (product_id, sale_date, amount, region) VALUES
(1, '2023-01-01', 100.00, 'East'),
(2, '2023-01-01', 150.00, 'West'),
(1, '2023-01-02', 200.00, 'East'),
(3, '2023-01-02', 120.00, 'South'),
(2, '2023-01-03', 180.00, 'West'),
(1, '2023-01-03', 220.00, 'East'),
(3, '2023-01-04', 140.00, 'South'),
(4, '2023-01-04', 300.00, 'North'),
(2, '2023-01-05', 250.00, 'West'),
(1, '2023-01-05', 280.00, 'East');
insert into sales(product_id, sale_date, amount, region) values
(1,'2023-01-01',200.00,'East');
题目:
1.计算每日销售额总和(分区按日期)
2.计算每个区域的总销售额
3.为每个产品计算其销售排名(按销售额降序)
4.计算每个区域每天的平均销售额
5.计算每个产品的销售累计总额
6.计算每个区域每个产品的销售总额
7.计算每个区域最近7天的平均销售额
8.为每个产品的销售记录添加序列号(按日期排序)
9.计算每个区域每天相对于前一天的销售额变化
10.计算每个产品的销售占比(销售额/总销售额)
自己可以先把这些最基础的窗口函数做完之后,再看下面的解析
答案:
复制代码
# 计算每日销售额总和(分区按日期)
SELECT *,sale_date, SUM(amount) OVER (PARTITION BY sale_date order by sale_date) AS total_daily_sales
FROM sales;
# 计算每个区域的总销售额
SELECT region, SUM(amount) OVER (PARTITION BY region) AS total_regional_sales
FROM sales;
# 为每个产品计算其销售排名(按销售额降序)
select product_id,rank() over (order by sum(amount) desc )as '销售排名' from sales group by product_id ;
# 计算每个区域每天的平均销售额
select *,avg(amount)over (partition by region,sale_date rows between unbounded preceding and unbounded following) from sales;
# 计算每个产品的销售累计总额
select *,sum(amount)over (partition by product_id) from sales;
# 计算每个区域每个产品的销售总额
select *,sum(amount)over (partition by product_id,region)from sales;
# 计算每个区域最近7天的平均销售额
with t1 as ( select *,dense_rank() over(partition by region order by sale_date)as ttime from sales )
select *,avg(amount)over(partition by region) from t1 where ttime<7;
;
# 为每个产品的销售记录添加序列号(按日期排序)
select *,dense_rank() over (partition by product_id order by sale_date)from sales;
# 计算每个区域每天相对于前一天的销售额变化
SELECT
a.sale_date,
a.region,
a.amount,
a.amount - LAG(a.amount) OVER (PARTITION BY a.region ORDER BY a.sale_date) AS daily_change
FROM sales a;
# 计算每个产品的销售占比(按总销售额
select *,sales.amount/sum(amount)over (partition by product_id)from sales;