MySQL——窗口函数(笔记整理)

什么是窗口函数?

简单来说就是 将 一个查询SQL 的结果集按指定的规则进行分区,每个分区可以看作是一个窗口,分区内的每一行,根据其所属分区内的行数据进行函数计算,获取计算结果,作为该行的窗口函数结果值

窗口函数和Group by的区别

-group by使用聚合函数,普通场景下的聚合函数是将多条记录聚合为一条(多到一)-窗口函数是每条记录都会执行,有几条记录执行完还是几条(多到多)

MySQL——窗口函数(笔记整理)_第1张图片

语法:
函数名(字段名) over(partition by <要分列的组> order by <要排序的列> rows between <数据范围>)

rows between 2 preceding and current row #本行和前面两行

rows between unbounded preceding and current row #本行和之前所有的行 #unbounded意为无限的

rows between current row and unbounded following # 本行和之后所有的行rows between 3 preceding and 1 following # 从前面三行和下面一行,总共五行

-- 当order by后面没有rows between时,窗口规范默认是取本行和之前所有的行

-- 当order by和rows between都没有时,窗口规范默认是分组下所有行

MySQL函数之——窗口函数

一、累计和:SUM(字段) over()

二、最大最小:MAX(字段)over()、MIN(字段)over()

三、移动平均:AVG(字段)over()

四、排名排序:Rank()over()

五、前后取值【相隔差】:LAG(字段,n)over()、LEAD(字段,n)over()

六、首位末位:first_value(字段)over()、last_value()over()

七、第N个:NTH_VALUE(expr,n)over()

八、分桶分箱(分等级)NTILE(n)over()

-- 窗口语法:函数名(字段名)over(子句)
【场景1】 累计和:sum(字段)over()

#示例:求每天的总金额
select order_date,payble,sum(payble) from order_info group by order_date order by order_date;
select order_date,payble, -- 数据排序
sum(payble) over (PARTITION BY order_date ORDER BY order_date) total1,
sum(payble) over (PARTITION BY order_date) total2
from order_info;


【场景2】最大最小:MAX(字段)over()、MIN(字段)over()

#示例:求每天的最早订单和最晚订单时间
select distinct order_date,
min(start_time) over(partition by order_date) mintime,
max(start_time) over(partition by order_date) maxtime
from order_info;

select order_date,min(start_time),max(start_time)
from order_info group by order_date order by order_date;

【场景3】移动平均:AVG(字段)OVER()  ***重点理解这题****

# 移动平均,查看每天包括前1天的平均金额
with a as(
select order_date,sum(payble) spay from order_info group by order_date)
select order_date,spay,
            avg(spay) over(order by order_date rows between 1 preceding and current row) rowvpay  from a;   #本行和前面1行,即题目的每天包括前一天


            
 【场景4】排名:RANK() OVER()

 # 查询order_detail 数据表中每个订单下价格降序排列的各个明细信息
select detail_id,order_id,amounts,
 # 顺序排序
    row_number() over(partition by order_id order by amounts desc) row_num,
    
    # 并列排序,会跳过重复的序号(如:12 12 14,其中第二个12是跳过的重复的,第三个为14)
    rank() over(partition by order_id order by amounts desc) ranks,
    
    # 并列排序,不会跳过重复的序号(如:14 14 15,不跳过重复值,两个14后第三个值还是15)
    dense_rank() over(partition by order_id order by amounts desc) dranks,
    
    #等级值百分比
    PERCENT_RANK() OVER(PARTITION BY order_id ORDER BY amounts DESC) pranks,
    # 累计分布值
    CUME_DIST() OVER(PARTITION BY order_id ORDER BY amounts DESC) cranks
from order_detail;
    


            
【场景5】前后取值:LAG(字段,n) OVER()、LEAD(字段,n) OVER()    

示例:计算每个订单与后一个订单的金额差【相隔用lead()】        
with a as(
select *,lead(payble,1) over(order by payble) pay2 from order_info)
select info_id,payble,pay2 ,pay2-payble 差值 from a;


【场景6】首位末位:FIRST_VALUE(字段) OVER()、LAST_VALUE(字段) OVER()

# 示例:info表中,每天第一个和最后一个订单记录的订单时间
select DISTINCT order_date, FIRST_VALUE(start_time) over (PARTITION BY order_date ) total1,
LAST_VALUE(start_time) over (PARTITION BY order_date ) total2
from order_info ;

*****多个查询结果表利用的嵌套,两个with x as()即可实现*********
-- 问题:比较每天与上周同一天(周一对周一)的订单总金额【隔几天用lead()】
select * from order_info;      dishes_count*payble总金额
with b as(
with a as(
select start_time,sum(dishes_count*payble) 订单总金额 from order_info group by date(start_time) order by date(start_time))
select date(start_time),订单总金额,lead(订单总金额,7) over(order by date(start_time)) 每周同一天的订单总金额 from a)
select *,订单总金额-每周同一天的订单总金额 每周同一天的订单总金额差值 from b;

【场景7】第N个:NTH_VALUE(expr, n) OVER()

示例:每个订单中价格第一和第二的菜的id号【排序,排第几第几用nth_value()】
select * from order_detail;
select DISTINCT order_id,amounts,
# desc降序后,nth_value(dishes_id,1)为价格排名第一对应的菜品编号
NTH_VALUE(dishes_id,1) over (PARTITION BY order_id ORDER BY amounts desc) id1,
# desc降序后,nth_value(dishes_id,2)为价格排名第二对应的菜品编号
NTH_VALUE(dishes_id,2) over (PARTITION BY order_id ORDER BY amounts desc) id2
from order_detail;
             


【场景8】分桶分箱:NTILE(n) OVER()

 示例:把菜品单价分成5个等级
select DISTINCT amounts, NTILE(5) over (ORDER BY amounts) nprice
from order_detail;

你可能感兴趣的:(sql,数据库)