• 2023.11.16 hivesql高阶函数之开窗函数


    目录

    1.开窗函数的定义

    2.数据准备

    3.开窗函数之排序

     需求:用三种排序方法查询学生的语文成绩排名,并降序显示

     4.开窗函数分组

    需求:按照科目来分类,使用三种排序方式来排序学生的成绩

     5.聚合函数与分组配合使用

    6.聚合函数同时和分组以及排序关键字配合使用

    --需求1:求出每个用户的总pv数,展示所有信息  默认第一行到最后一行

    --需求2:求出每个用户截止到当天,累积的总pv数  默认第一行到当前行

    做题思路,开窗函数核心:保证输出结果的记录数和输入的数据记录数一致 

    7.窗口范围控制

    1.默认第一行到当前行

    2.第一行到当前行,等效于rows between ..不写,默认就是第一行到当前行

    3.向前3行到当前行

    4.向前3行 向后1行

     5.当前行到最后一行,第一行到最后一行

    8.其他函数

        1.ntile平分:

    注意ntile规则:尽量平均分配 ,优先满足最小(编号1)的桶,彼此最多不相差1个。

    --需求:统计每个用户pv数最多的前3分之1天。--理解:将数据根据cookieid分 根据pv倒序排序 排序之后分为3个部分 取第一部分


    1.开窗函数的定义

    - 窗口:可以理解为操作数据的范围,窗口有大有小,本窗口中操作的数据有多有少。

    - 可以简单地解释为类似于聚合函数的计算函数,但是通过GROUP BY子句组合的常规聚合会隐藏正在聚合的各个行,最终输出一行

    -而窗口函数聚合后还可以访问当中的各个行,并且可以将这些行中的某些属性添加到结果集中。

    开窗函数格式:  select ... 开窗函数 over(partition by 分组字段名 order by 排序字段名 asc|desc) ... from 表名; 

    -- 如果有分组操作,select后的字段要么在聚合函数内,要么在group by 后出现

    -- 开窗函数: hive和mysql8都能使用

    -- 开窗函数本质在表后新增了一列

    -- 聚合开窗函数: max min sum avg count

    2.数据准备

    数据文件score.txt

    1. --数据准备
    2. create table students(
    3. s_id int,
    4. s_name string,
    5. subject string,
    6. score double,
    7. class string
    8. )row format delimited
    9. fields terminated by '\t';
    10. --加载数据
    11. load data inpath '/input/score.txt' into table students;
    12. --验证数据
    13. select * from students;

     
    

    3.开窗函数之排序

    1. --查询最高分的学生
    2. select max(score) from students; -- 99
    3. -- 聚合函数配合over()使用,也可以叫开窗函数
    4. --查询最高分的学生,并附上他的名字
    5. select s_name,
    6. max(score) over() --每一个学生都会匹配一个最高分,数据不正确
    7. from students;

    -- 排序开窗函数: row_number  rank  dense_rank

    -- 排序函数必须配合over(order by 排序字段 asc|desc)

    row_number: 巧记: 1234   特点: 唯一且连续

    dense_rank: 巧记: 1223   特点: 并列且连续

    rank   : 巧记: 1224   特点: 并列不连续

     需求:用三种排序方法查询学生的语文成绩排名,并降序显示

    1. select s_name,subject,score,
    2. row_number() over (order by score desc ) ,--唯一且连续
    3. dense_rank() over (order by score desc ) ,--并列且连续
    4. rank() over (order by score desc ) --并列不连续
    5. from students
    6. where subject = '语文';

     4.开窗函数分组

    -- 开窗函数分组

    -- 注意不能用group by ,需要使用partition by,可以理解成partition by是group by的子句

    -- 演示排序函数和分组配合使用: 先分组再组内排序

    需求:按照科目来分类,使用三种排序方式来排序学生的成绩

    1. select *,
    2. row_number() over (partition by subject order by score desc ),
    3. dense_rank() over (partition by subject order by score desc ),
    4. rank() over (partition by subject order by score desc )
    5. from students;

     5.聚合函数与分组配合使用

    1. -- 演示聚合函数和分组配合使用
    2. -- 普通分组
    3. select s_name,
    4. max(score)
    5. from students group by s_name;

    查询每个学生的信息,按照文理科分类,以及平均分

    1. -- 开窗分组
    2. select *,
    3. avg(score) over(partition by class)
    4. from students;

    6.聚合函数同时和分组以及排序关键字配合使用

    1. -- 演示聚合函数同时和分组以及排序关键字配合使用
    2. -- 数据准备
    3. ---建表并且加载数据
    4. create table website_pv_info(
    5. cookieid string,
    6. createtime string, --day
    7. pv int
    8. ) row format delimited
    9. fields terminated by ',';
    10. -- 建表
    11. create table website_url_info (
    12. cookieid string,
    13. createtime string, --访问时间
    14. url string --访问页面
    15. ) row format delimited
    16. fields terminated by ',';
    17. -- 加载数据
    18. load data inpath '/input/website_pv_info.txt' into table website_pv_info;
    19. load data inpath '/input/website_url_info.txt' into table website_url_info;
    20. -- 查询数据
    21. select * from website_pv_info;
    22. select * from website_url_info;

     

    --需求1:求出每个用户的总pv数,展示所有信息  默认第一行到最后一行

    cookie是记住用户记录的一个文件,代表一个用户

    1. select *,
    2. sum(pv) over (partition by cookieid)
    3. from website_pv_info;

     

    --需求2:求出每个用户截止到当天,累积的总pv数  默认第一行到当前行

    --sum(...) over( partition by... order by ... ),在每个分组内,连续累积求和

    1. select *,
    2. sum(pv) over (partition by cookieid order by createtime)
    3. from website_pv_info;

    做题思路,开窗函数核心:保证输出结果的记录数和输入的数据记录数一致 

    7.窗口范围控制

    rows between
       - preceding:往前
       - following:往后
       - current row:当前行
       - unbounded:起点
       - unbounded preceding 表示从前面的起点  第一行
       - unbounded following:表示到后面的终点  最后一行

    1.默认第一行到当前行

    1. select cookieid,createtime,pv,
    2. sum(pv) over(partition by cookieid order by createtime) as pv1
    3. from website_pv_info;

    2.第一行到当前行,等效于rows between ..不写,默认就是第一行到当前行

    1. select cookieid,createtime,pv,
    2. sum(pv) over(partition by cookieid order by createtime
    3. rows between unbounded preceding and current row) as pv2
    4. from website_pv_info;

    3.向前3行到当前行

    1. --向前3行至当前行
    2. select cookieid,createtime,pv,
    3. sum(pv) over(partition by cookieid order by createtime
    4. rows between 3 preceding and current row) as pv4
    5. from website_pv_info;

    1+5+7=13   ,    1+5+7+3=16   ,  5+7+3+2=17  ,   7+3+2+4=16     ,   3+2+4+4=13

    相当于查询今天以及前三天的总浏览量,在现实中常称为网站的'最近3天访问量'.

    4.向前3行 向后1行

    1. select cookieid,createtime,pv,
    2. sum(pv) over(partition by cookieid order by createtime
    3. rows between 3 preceding and 1 following) as pv5
    4. from website_pv_info;

    1+5+7+3+2=18  ,   5+7+3+2+4=21

     5.当前行到最后一行,第一行到最后一行

    1. --当前行至最后一行
    2. select cookieid,createtime,pv,
    3. sum(pv) over(partition by cookieid order by createtime
    4. rows between current row and unbounded following) as pv6
    5. from website_pv_info;
    6. --第一行到最后一行 也就是分组内的所有行
    7. select cookieid,createtime,pv,
    8. sum(pv) over(partition by cookieid order by createtime
    9. rows between unbounded preceding and unbounded following) as pv6
    10. from website_pv_info;

    8.其他函数

        1.ntile平分:

    注意ntile规则:尽量平均分配 ,优先满足最小(编号1)的桶,彼此最多不相差1个。

    其他开窗函数: ntile   lag和lead   first_value和last_value

    ntile(x)功能: 将分组排序之后的数据分成指定的x个部分(x个桶)   
            注意ntile规则:尽量平均分配 ,优先满足最小(编号1)的桶,彼此最多不相差1个。

    lag: 用于统计窗口内往上第n行值
    lead:用于统计窗口内往下第n行值

    first_value: 取分组内排序后,截止到当前行,第一个值
    last_value : 取分组内排序后,截止到当前行,最后一个值

    注意: 窗口函数结果都是单独生成一列存储对应数据

    1. -- 演示ntile
    2. --把每个分组内的数据均匀分为3桶
    3. SELECT
    4. cookieid,
    5. createtime,
    6. pv,
    7. ntile(3) OVER(PARTITION BY cookieid ORDER BY createtime) AS rn2
    8. FROM website_pv_info
    9. ORDER BY cookieid,createtime;

    --需求:统计每个用户pv数最多的前3分之1天。
    --理解:将数据根据cookieid分 根据pv倒序排序 排序之后分为3个部分 取第一部分

    1. with tmp as (SELECT
    2. cookieid,
    3. createtime,
    4. pv,
    5. NTILE(3) OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn
    6. FROM website_pv_info)
    7. SELECT * from tmp where rn =1;

     

    1. --lag 用于统计窗口内往上第n行值
    2. select cookieid, createtime, url,
    3. row_number() over (partition by cookieid order by createtime) rn,
    4. lag(createtime, 1) over (partition by cookieid order by createtime) la1,
    5. lag(createtime, 2, '2000-01-01 00:00:00') over (partition by cookieid order by createtime) la2
    6. from website_url_info;
    7. --lead 用于统计窗口内往下第n行值
    8. select cookieid, createtime, url,
    9. row_number() over (partition by cookieid order by createtime) rn,
    10. lead(createtime, 1) over (partition by cookieid order by createtime) la1,
    11. lead(createtime, 2, '2000-01-01 00:00:00') over (partition by cookieid order by createtime) la2
    12. from website_url_info;
    13. --FIRST_VALUE 取分组内排序后,截止到当前行,第一个值
    14. select cookieid, createtime, url,
    15. row_number() over (partition by cookieid order by createtime) rn,
    16. first_value(url) over (partition by cookieid order by createtime) fv
    17. from website_url_info;
    18. --LAST_VALUE 取分组内排序后,截止到当前行,最后一个值
    19. select cookieid, createtime, url,
    20. row_number() over (partition by cookieid order by createtime) rn,
    21. last_value(url) over (partition by cookieid order by createtime rows between unbounded preceding and unbounded following) fv
    22. from website_url_info;

  • 相关阅读:
    蓝桥杯1049
    VPP以太网接口模式
    文件上传漏洞
    前端三剑客 - HTML
    文件操作(下)
    GitHub 开源了多款字体「GitHub 热点速览 v.22.48」
    seata 1.5.2 保姆级教程
    「Python条件结构」根据三种商品的价格求应付的金额
    Waitlist ,验证产品想法是否可行的一个方法
    Linux安装RabbitMQ步骤分享
  • 原文地址:https://blog.csdn.net/m0_49956154/article/details/134434820