• Hive 【Hive(七)窗口函数练习】


    窗口函数案例

    数据准备

    1)建表语句

    1. create table order_info
    2. (
    3. order_id string, --订单id
    4. user_id string, -- 用户id
    5. user_name string, -- 用户姓名
    6. order_date string, -- 下单日期
    7. order_amount int -- 订单金额
    8. );

    2)装载语句

    1. insert overwrite table order_info
    2. values ('1', '1001', '小元', '2022-01-01', '10'),
    3. ('2', '1002', '小海', '2022-01-02', '15'),
    4. ('3', '1001', '小元', '2022-02-03', '23'),
    5. ('4', '1002', '小海', '2022-01-04', '29'),
    6. ('5', '1001', '小元', '2022-01-05', '46'),
    7. ('6', '1001', '小元', '2022-04-06', '42'),
    8. ('7', '1002', '小海', '2022-01-07', '50'),
    9. ('8', '1001', '小元', '2022-01-08', '50'),
    10. ('9', '1003', '小辉', '2022-04-08', '62'),
    11. ('10', '1003', '小辉', '2022-04-09', '62'),
    12. ('11', '1004', '小猛', '2022-05-10', '12'),
    13. ('12', '1003', '小辉', '2022-04-11', '75'),
    14. ('13', '1004', '小猛', '2022-06-12', '80'),
    15. ('14', '1003', '小辉', '2022-04-13', '94');

    需求

    1)统计每个用户截至每次下单的累积下单总额

    这里使用基于行的窗口函数,起点是第一行,终点是当前行,并根据每个用户id分区,根据下单日期排序;因为需求是累计下单总额,所以窗口范围是从第一行到当前行。

    1. -- 1)统计每个用户截至每次下单的累积下单总额
    2. select user_id,
    3. user_name,
    4. order_id,
    5. order_date,
    6. order_amount,
    7. sum(order_amount) over(partition by user_id order by order_date rows between unbounded preceding and current row ) sum_amount
    8. from order_info;

     运行结果:

    2)统计每个用户截至每次下单的当月累积下单总额

    这里使用了 substring 函数,它作为 partition by 后面的第二个字段,意味着先根据 user_id 分区之后再根据 日期的 1~7 位(也就是 年份-月份)进行分区,这样就巧妙的将每个用户不同的月份可以进行窗口函数的累计求和。

    1. select user_id,
    2. user_name,
    3. order_id,
    4. order_date,
    5. order_amount,
    6. sum(order_amount) over(partition by user_id ,substring(order_date,1,7) order by order_date rows between unbounded preceding and current row ) sum_amount
    7. from order_info

    运行结果:

    3)统计每个用户每次下单距离上次下单相隔的天数(首次下单按0天算)

    这里用到一个新的函数 datediff(),它是用来计算两个日期间隔的;这道题的核心在于使用 lag 函数来获取上一行的值 last_date,然后用 datediff 函数进行差值计算得到天数。

    注意:lag 函数和 lead 函数是不需要声明窗口范围的。

    1. -- 3)统计每个用户每次下单距离上次下单相隔的天数(首次下单按0天算)
    2. select user_id,
    3. user_name,
    4. order_id,
    5. order_date,
    6. order_amount,
    7. nvl(datediff(order_date,last_date),0) diff
    8. from (
    9. select
    10. order_id,
    11. user_id,
    12. user_name,
    13. order_date,
    14. order_amount,
    15. lag(order_date,1,null) over(partition by user_id order by order_date) last_date
    16. from order_info
    17. )t1;

    运行结果: 

    4)查询所有下单记录以及每个用户的每个下单记录所在月份的首/末次下单日期

    这里使用了 first_value 和 last_value 函数,同样分区规则是先根据 user_id 再根据 order_date 进行分区的,其中 last_value 需要声明窗口范围,我们取从第一行到最后一行;first_value 没有声明窗口范围,则会默认按照 基于列 的窗口函数 between unbounded preceding and current row,因为我们比较的是日期,所以即使每次移动窗口也都会取小于当前日期的值。

    1. -- 4)查询所有下单记录以及每个用户的每个下单记录所在月份的首/末次下单日期
    2. select user_id,
    3. user_name,
    4. order_id,
    5. order_date,
    6. order_amount,
    7. first_value(order_date,false) over (partition by user_id,substring(order_date,1,7) order by order_date) first_date,
    8. last_value(order_date,false) over (partition by user_id,substring(order_date,1,7) order by order_date rows between unbounded preceding and unbounded following) last_date
    9. from order_info;

    运行结果:

    5)为每个用户的所有下单记录按照订单金额进行排名

    这里使用 row_number() ,order by 是根据 order_amount 进行排序,排名的结果也是按照 order_amount 排名。 

    1. -- 5)为每个用户的所有下单记录按照订单金额进行排名
    2. select user_id,
    3. user_name,
    4. order_id,
    5. order_date,
    6. order_amount,
    7. row_number() over (partition by user_id order by order_amount) rank
    8. from order_info;

    运行结果:

  • 相关阅读:
    jQuery、vue、小程序、uni-app中的本地存储数据和接受数据是什么?
    MongoShake迁移mongodb数据库
    STM32_USART
    Day21:算法篇之动态规划dp
    【人工智能】机器学习入门之监督学习(一)有监督学习
    shiro-第一篇-基本介绍及使用
    LeetCode每日一题——779. 第K个语法符号
    微服务学习 | Ribbon负载均衡、Nacos注册中心、微服务技术对比
    flask-vue-sqlite3-->api接口-优化版本
    【Netty 从成神到升仙系列 四】让我们一起探索 Netty 中的零拷贝
  • 原文地址:https://blog.csdn.net/m0_64261982/article/details/133611410