HiveSQL——条件判断语句嵌套windows子句的应用

注:参考文章:

SQL条件判断语句嵌套window子句的应用【易错点】--HiveSql面试题25_sql剁成嵌套判断-CSDN博客文章浏览阅读920次,点赞4次,收藏4次。0 需求分析需求:表如下user_idgood_namegoods_typerk1hadoop1011hive1221sqoop2631hbase1041spark1351flink2661kafka1471oozie108以上数据._sql剁成嵌套判断https://blog.csdn.net/godlovedaniel/article/details/118220935

0 需求

基于下表的表结构及数据,求出每个用户每次搜索非广告类型的商品位置排序。假设字段goods_type为26代表该商品类型是广告。

想达到的效果:

1 数据加载

sql 复制代码
--建表
create table window_goods_test (
user_id int,    --用户id
goods_name string,  --商品名称
goods_type int, --标识每个商品的类型,比如广告,非广告
rk int  --这次搜索下商品的位置,比如第一个广告商品就是1,后面的依次2,3,4...
)ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

-- 加载数据
load data local  inpath '/opt/module/hive_data/window_goods_test.txt' into table window_goods_test ;

vim window_goods_test.txt

1 hadoop 10 1

1 hive 12 2

1 sqoop 26 3

1 hbase 10 4

1 spark 13 5

1 flink 26 6

1 kafka 14 7

1 oozie 10 8

2 数据分析

代码分析:最开始的思路:先过滤掉非广告的商品,再重新排序

sql 复制代码
select user_id,
       goods_name,
       goods_type,
       rk,
       if(goods_type != 26,row_number() over (partition by user_id order by rk),null) as rk1
from window_goods_test;

输出结果如下:显然没有达到预期的结果。

出错原因在于对窗口函数的执行原理及顺序不了解,可以通过执行计划来判断SQL执行顺序。

sql 复制代码
explain 
select user_id,
       goods_name,
       goods_type,
       rk,
       if(goods_type != 26,row_number() over (partition by user_id order by rk),null) as rk1
from window_goods_test;

具体执行步骤如下:

(1)扫描表

(2)按照user_id分组

(3)按照user_id和rk进行升序排序

(4)执行row_number()函数进行分析

(5)使用if进行判断

由执行计划可以得出 if函数是在row_number()函数之后执行的

上述sql可以拆解为三部分进行执行:

step1:扫描表,获取select的结果集

sql 复制代码
select user_id,
       goods_name,
       goods_type,
       rk
from window_goods_test;

step2:执行窗口函数

sql 复制代码
select user_id,
    goods_name,
    goods_type,
    rk,
   row_number() over (partition by user_id order by rk) as rk1
from window_goods_test;

**step3:**基于step2结果集执行 if判断

因此正确代码如下:

方式一:union all 拆解成两段逻辑

sql 复制代码
-- 第一段逻辑:先限制goods_type != 26,再排序
select
    user_id,
    goods_name,
    goods_type,
    rk,
    row_number() over (partition by user_id order by rk) as rk1
from window_goods_test
where goods_type != 26
union all
-- 第二段逻辑:将goods_type = 26的记录的rk1 直接记为null
select
    user_id,
    goods_name,
    goods_type,
    rk,
    null as rk1
from window_goods_test
where goods_type = 26
order by rk;

上述代码的缺点:window_goods_test表 需要扫描两次,显然不是最优解。

优化的解题思路为:

方式二:

step1: partition by分组中先进行 if 语句过滤 ,如果goods_type!=26则取对应的user_id 进行分组,如果goods_type=26 则置为随机数rand(), 再按照随机数分组

ps: 这里采用随机数是考虑到万一 goods_type=26的记录数很多,通过rand()随机分组可以将key值打散避免数据倾斜

sql 复制代码
select
    user_id,
    goods_name,
    goods_type,
    rk,
    row_number() over (partition by
        if(goods_type != 26, user_id, rand())
        order by rk) rk1
from window_goods_test

step2:在step1的外侧利用 if函数进一步判断

sql 复制代码
select
    user_id,
    goods_name,
    goods_type,
    rk,
    if(goods_type != 26,
        row_number() over (partition by if(goods_type != 26, user_id, rand()) order by rk),
        null) rk1
from window_goods_test

3 小结

通过本案例得出的结论:

  • case when或if语句中嵌套窗口函数时,条件判断语句的执行顺序是在窗口函数之后的;
  • 窗口函数partition by 子句中是允许嵌套条件判断语句的;
相关推荐
Raas10016 分钟前
MAI Gateway(魔芋企业级AI网关)技术揭秘:AI网关支持哪些模型?从原理到落地
大数据·人工智能·网关·gateway·mai gateway·企业级产品
YangYang9YangYan3 小时前
2026 校招商品分析岗位 JD 拆解,核心指标、工具与面试考点
大数据·数据库·数据分析
大大大大晴天3 小时前
OpenMetadata VS DataHub VS Atlas VS Gravitino
大数据
Qyr996 小时前
2026全球汽车碳刷行业发展全景分析报告
大数据
蓝速科技7 小时前
便民服务大厅 AI 数字人一体机场景适配与落地指南丨蓝速科技
大数据·网络·数据结构·人工智能·自然语言处理·数据分析·运维开发
精益数智工坊7 小时前
云计算环境数据怎么同步?云计算集成方案有哪些?
大数据·人工智能·数据挖掘·数据可视化
huashengzsj8 小时前
什么是DMS经销商管理系统?国内经销商管理系统有哪些品牌
大数据
IT毕设梦工厂9 小时前
计算机毕业设计选题推荐:基于大数据的草鱼价格分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hadoop·python·数据挖掘·数据分析·课程设计·大数据毕设项目
辛迪聊物业数字化10 小时前
智慧社区物业管理软件新手部署与实操指南
大数据·php
字节跳动数据平台10 小时前
模型再强,为什么 Demo 还是进不了生产?
大数据