ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql 自我练习基础 7:开窗函数 charlly练习版(CDA数据库)

2021-10-06 13:35:11  阅读:189  来源: 互联网

标签:no over 练习 order 订单 amount tab mysql charlly


create database CDA;
use CDA;

create table order_tab(
    order_id int, 
    user_no varchar(3), 
    amount int, 
    create_date date 
);

insert into order_tab values 
(1,'001',100,'2019-01-01'), 
(2,'001',300,'2019-01-02'), 
(3,'001',500,'2019-01-02'), 
(4,'001',800,'2019-01-03'), 
(5,'001',900,'2019-01-04'), 
(6,'002',500,'2019-01-03'), 
(7,'002',600,'2019-01-04'), 
(8,'002',300,'2019-01-10'), 
(9,'002',800,'2019-01-16'), 
(10,'002',800,'2019-01-22'); 

select * from order_tab;

-- 查询所有订单的订单总金额
-- 聚合函数用于开窗计算:开窗函数名([<字段名>]) over([partition by <分组字段>] [order by <排序字段> [desc]] [<窗口分区>])

select *,sum(amount) over() as 订单总金额 from order_tab;
#当over中没有指定分区、排序和滑动窗口范围时,表中所有记录为一个区,默认计算的是分区内第一行到最后一行的值范围内的所有记录

-- 查询每个用户的订单总金额
select *,sum(amount) over(partition by user_no) as 订单总金额 from order_tab;
#当over中指定分区,但是没有指定排序和滑动窗口范围时,默认计算的是分区内所有行

-- 查询每个用户每天的订单总金额
select *,sum(amount) over(partition by user_no,create_date) as 订单总金额 from order_tab;

-- 查询每个用户按照下单时间顺序的累计订单金额
select *,sum(amount) over(partition by user_no order by create_date) as 累计订单金额 from order_tab;
#当over中指定排序,但是没有指定滑动窗口范围时,默认计算的是第一行到当前行的值范围内的所有记录             无滑动窗口指定行时   默认就是指定值来计算

-- 查询每个用户按照订单编号顺序,前一笔到后后一笔订单的平均订单金额(基于行)
select *,avg(amount) over(partition by user_no order by order_id rows between 1 preceding and 1 following) as 平均订单金额 from order_tab;

-- 查询每个用户按照订单编号顺序,前一笔到后两笔订单的平均订单金额(基于值)
select *,avg(amount) over(partition by user_no order by order_id range between 1 preceding and 2 following) as 平均订单金额 from order_tab;
#当over中指定滑动窗口范围,计算的是指定的值范围内的所有记录

-- 查询每个用户按照下单时间顺序的前一天到后一天的平均订单金额(基于值)
select *,avg(amount) over(partition by user_no order by create_date range between interval 1 day preceding and interval 1 day following) as 平均订单金额 from order_tab;
#当over中指定滑动窗口范围,计算的是指定的值范围内的所有记录
#当over中指定了排序 没有指定滑动窗口范围时  默认是是基于值来计算的

-- 查询每个用户订单金额排名
select *,row_number() over(partition by user_no order by amount desc) as 订单金额排名 from order_tab;-- row_number()为静态窗口函数 无需指定滑动窗口范围,指定了滑动窗口后不会报错但是无效
select *,
row_number() over(partition by user_no order by amount desc) as 订单金额排名1,
dense_rank() over(partition by user_no order by amount desc) as 订单金额排名2,
rank() over(partition by user_no order by amount desc) as 订单金额排名3
from order_tab;



-- 查询每个用户订单金额排名前三的订单
#1
select *,
dense_rank() over(partition by user_no order by amount desc) as 订单金额排名
from order_tab
where 订单金额排名<=3;#报错:where 中不能引用别名,因为别名是在select中产生的 ,标的查询顺序 是from  where  select

#2
select *,
dense_rank() over(partition by user_no order by amount desc) as 订单金额排名
from order_tab
where dense_rank() over(partition by user_no order by amount desc)<=3;#报错:where 中不能使用开窗函数(开窗函数本质上是聚合函数,where中不能用聚合函数),并且本句中开窗函数是在select中产生的 ,标的查询顺序 是from  where  select,两个错误原因

#3.
select *,
dense_rank() over(partition by user_no order by amount desc) as 订单金额排名
from order_tab; -- 先把该表写出来 然后再此表基础上进行筛选即可

select *
from
(select *,
dense_rank() over(partition by user_no order by amount desc) as 订单金额排名
from order_tab) as t
where 订单金额排名<=3;
#与1.不一样的是第一步执行的是括号中子查询,该步骤中    订单金额排名   已经产生



-- 查询每个用户按照日期顺序,订单金额的每日增长率
select
user_no,
create_date,
sum(amount) as 订单总金额,
lag(订单总金额,1) over(partition by user_no order by create_date) 
from order_tab
group by user_no,create_date;# 报错,lag中引用了同是select语句中的别名


select
user_no,
create_date,
sum(amount) as 订单总金额,
lag(sum(amount),1) over(partition by user_no order by create_date) as 前一天的订单总金额
from order_tab
group by user_no,create_date; 


#老师语句
select 
    user_no,
    create_date,
    sum(amount) as 订单总金额,
    lag(sum(amount),1) over(partition by user_no order by create_date) as 前一天的订单总金额,
    (sum(amount)-lag(sum(amount),1) over(partition by user_no order by create_date))/lag(sum(amount),1) over(partition by user_no order by create_date) as 每日增长率
from order_tab
group by user_no,create_date;



select * from order_tab;
-- 查询每个用户上一个订单距离当前订单的间隔天数 (由于是对每个用户每个订单进行数据,则后续不需要进行聚合,否则输出不对)
-- charlly练习 步骤1.每个用户上一个订单时间2.计算上个订单 与当前订单的间隔天数
select *,
lag(create_date,1) over(partition by user_no order by create_date) as 上个订单时间,
timestampdiff(day,lag(create_date,1) over(partition by user_no order by create_date),create_date) as 上一个订单距离当前订单的间隔天数
from order_tab; 
-- 疑问 这里order by 该用create_date还是order_id,有可能存在两种情况1.一个用户在同一天下了两单 create_date是否适用2.这里的order_id比较理想化,如果order_id 实际上不是按照用户来的而是交错的

-- 老师代码
select 
    *,
    lag(create_date,1) over(partition by user_no order by order_id ) as 前一笔订单的下单日期, -- 该计算的是 第一行到当前行还是,整个计算的整个分区?
    timestampdiff(day,lag(create_date,1) over(partition by user_no order by order_id),create_date) as 间隔天数
 from order_tab 
 order by  order_id desc;-- 老师代码没有这句降序,添加这句是为了验证 整个表格的降序是受最后这个order by 影响(对结果不影响,出来了结果之后按照指定顺序再排列),开窗函数里面的升降序只会影响开窗函数的返回值,不影响前面字段的排列方式





-- 查询每个用户第一笔订单和最后一笔订单的下单日期
#老师代码

-- 方法一
select 
    *,
    first_value(create_date) over(partition by user_no order by create_date rows between unbounded preceding and unbounded following) as 第一笔订单的下单日期,
    last_value(create_date) over(partition by user_no order by create_date rows between unbounded preceding and unbounded following) as 最后一笔订单的下单日期
from order_tab;

-- 方法二
select 
    *,
    min(create_date) over(partition by user_no) as 第一笔订单的下单日期,
    max(create_date) over(partition by user_no) as 最后一笔订单的下单日期
from order_tab;



-- charlly 练习按照题目要求呈现:每个用户第一笔订单和最后一笔订单的下单日期
select user_no,第一笔订单的下单日期,最后一笔订单的下单日期
from
(select *,
min(create_date) over(partition by user_no ) as 第一笔订单的下单日期,
max(create_date) over(partition by user_no) as 最后一笔订单的下单日期
from order_tab) as t
group by user_no;

-- charlly 练习按照题目要求呈现:每个用户第一笔订单和最后一笔订单的下单日期
# 方法二
select user_no,
min(create_date) as 第一笔订单的下单日期,
max(create_date)  as 最后一笔订单的下单日期
from order_tab
group by user_no;

 

标签:no,over,练习,order,订单,amount,tab,mysql,charlly
来源: https://www.cnblogs.com/charlly/p/15371090.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有