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 子句中是允许嵌套条件判断语句的;
相关推荐
zhang98800001 分钟前
储能领域大数据平台的设计中如何使用 Hadoop、Spark、Flink 等组件实现数据采集、清洗、存储及实时 / 离线计算,支持储能系统分析与预测
大数据·hadoop·spark
老蒋新思维6 分钟前
存量竞争下的破局之道:品牌与IP的双引擎策略|创客匠人
大数据·网络·知识付费·创客匠人·知识变现
Lx3521 小时前
Hadoop日志分析实战:快速定位问题的技巧
大数据·hadoop
喂完待续4 小时前
【Tech Arch】Hive技术解析:大数据仓库的SQL桥梁
大数据·数据仓库·hive·hadoop·sql·apache
SelectDB5 小时前
5000+ 中大型企业首选的 Doris,在稳定性的提升上究竟花了多大的功夫?
大数据·数据库·apache
最初的↘那颗心5 小时前
Flink Stream API 源码走读 - window 和 sum
大数据·hadoop·flink·源码·实时计算·窗口函数
Yusei_05237 小时前
迅速掌握Git通用指令
大数据·git·elasticsearch
一只栖枝13 小时前
华为 HCIE 大数据认证中 Linux 命令行的运用及价值
大数据·linux·运维·华为·华为认证·hcie·it
喂完待续18 小时前
Apache Hudi:数据湖的实时革命
大数据·数据仓库·分布式·架构·apache·数据库架构
青云交18 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵治理与出行效率提升中的应用(398)
java·大数据·flink·大数据可视化·拥堵预测·城市交通治理·实时热力图