hive sql子单元查找组合单元信息

1. 背景

店铺卖东西,会将一部分子商品(单个商品,sku 粒度)打包到一起,变成一个组合商品去售卖。

用户买东西,可能会买多个组合商品。

数仓这边拿到的数据,全是已经拆分到子商品的订单商品数据,也就是说:用户买的时候是组合商品,只有一条订单数据,但数仓表中保存的全是子商品对应的订单数据,会有多条订单数据,大概示意如下。

用后购买商品产生的订单信息:

order_id(订单id)combine_goods_id(组合商品id)
11
22

数仓得到的拆分之后的订单信息(order):

CREATE EXTERNAL TABLE `zhibo_test.order`(`order_id` string COMMENT '订单 id',`goods_id` string COMMENT '商品 id'
)
COMMENT '订单表'

数据:

order_id(订单id)goods_id(子商品id)
11
13
12
24
26
25
27

组合商品 1 包含 3 个子商品,子商品 id 分别为:1、2、3,价格都是 100。

组合商品 2 包含 4 个子商品,子商品 id 分别为:4、5、6、7,价格都是 100。

数仓中的组合商品维表信息(dim_combine_goods):

CREATE EXTERNAL TABLE `zhibo_test.dim_combine_goods`(`combine_goods_id` string COMMENT '组合商品 id',`combine_goods_name` string COMMENT '组合商品名称',`goods_id` string COMMENT '商品 id'
)
COMMENT '组合商品维表'

数据:

combine_goods_id(组合商品id)combine_goods_name(组合商品名称)goods_id(子商品id)
1组合商品11
1组合商品12
1组合商品13
11组合商品111
11组合商品112
11组合商品113
2组合商品24
2组合商品25
2组合商品26
2组合商品27
3组合商品31
3组合商品35

组合商品维表中的数据说明:

  1. 一个子商品,可以属于多个不同的组合商品,参考子商品 1(属于组合商品 1 和 3)、5(属于组合商品 2 和 3)。
  2. 相同的子商品组合,可以有不同的组合商品信息,参考组合商品 1 和 11,他们的子商品都是 1、2、3。

此时,我要判断数仓中的订单信息数据,每个订单中的子商品所属的组合商品 id 是哪个。

2. 解决方案

这种情况下,是不能直接使用子商品 id 和组合商品维保进行关联的,直接关联的话,由于一个子商品会同时属于多个不同的组合商品,所以会造成很大的数据膨胀,并且关联完的数据,也不是我们需要的结果。

将数仓订单表,根据订单 id 进行分组,然后将子商品 id 聚合,具体处理为:concat_ws('-', collect_set(goods_id)),也就是将订单中的所有子商品 id 聚合起来,然后使用 - 连接成字符串,然后将组合商品维表的数据,根据组合商品 id 分组,然后将子商品 id 聚合,和订单中的行为保持一致:concat_ws('-', collect_set(goods_id)),最后使用聚合之后的子商品 id 字符串进行关联,查询对应的组合商品 id 信息。实例 sql 如下:

with
order_info as (select order_id-- 这儿使用 collect_set 和 collect_list 效果一样,主要看自己的数据质量,只要是子商品没有重复即可-- 使用 concat_ws 函数将 collect_set 的数组结果拼接起来变成字符串,方便后续的比较。-- 	通过实验,直接使用 collect_set 的数据结果也是可以直接 join 的,但是数组之间是不可以直接使用 = 去判断是否相等的,所以还是转化为字符串这种基本数据类型比较好。,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom zhibo_test.`order`group by order_id
)
,combine_goods_info as (select combine_goods_id,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom zhibo_test.dim_combine_goodsgroup by combine_goods_id
)select a.order_id,c.combine_goods_id,b.goods_id
from order_info as a
join zhibo_test.`order` as b
on a.order_id = b.order_id
left join combine_goods_info as c
on a.goods_id_set = c.goods_id_set

运行完上面的 SQL 之后,发现结果中的 combine_goods_id 字段全是 null

image-20231207184515744

经排查发现,由于子商品的顺序在订单表和组合商品维表中的顺序不同,两个 SQL 对子商品 collect_set() 之后的数组结果,里面的顺序也是不同的,因此对其进行优化,优化之后的 SQL 如下:

with
order_info as (select order_id-- 这儿使用 collect_set 和 collect_list 效果一样,主要看自己的数据质量,只要是子商品没有重复即可-- 使用 concat_ws 函数将 collect_set 的数组结果拼接起来变成字符串,方便后续的比较。-- 	通过实验,直接使用 collect_set 的数据结果也是可以直接 join 的,但是数组之间是不可以直接使用 = 去判断是否相等的,所以还是转化为字符串这种基本数据类型比较好。,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select order_id,goods_idfrom zhibo_test.`order`-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by order_id
)
,combine_goods_info as (select combine_goods_id,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select combine_goods_id,goods_idfrom zhibo_test.dim_combine_goods-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by combine_goods_id
)select a.order_id,c.combine_goods_id,b.goods_id
from order_info as a
join zhibo_test.`order` as b
on a.order_id = b.order_id
left join combine_goods_info as c
on a.goods_id_set = c.goods_id_set

运行优化之后的 SQL,发现结果正确,所有的订单商品都找到了对应的组合商品信息

image-20231207184927848

但是,订单表中,order_id 为 1 的数据本来只有 3 条,现在的结果却有 6 条,明显膨胀了。

经过排查可以发现,组合商品维表中,由子商品:1、2、3 组合成的组合商品有两个,分别对应的组合商品 id 为:1、11,因此通过 concat_ws('-', collect_set(goods_id)) as goods_id_set 的结果进行 join 连接,会造成数据的膨胀。

解决方法也很简单,在组合商品维表中,如果相同子商品集合会对应多个组合商品的话,我们取其一即可,也可以将多个组合商品的信息合并起来。下面演示选择其一的 SQL:

with
order_info as (select order_id-- 这儿使用 collect_set 和 collect_list 效果一样,主要看自己的数据质量,只要是子商品没有重复即可-- 使用 concat_ws 函数将 collect_set 的数组结果拼接起来变成字符串,方便后续的比较。-- 	通过实验,直接使用 collect_set 的数据结果也是可以直接 join 的,但是数组之间是不可以直接使用 = 去判断是否相等的,所以还是转化为字符串这种基本数据类型比较好。,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select order_id,goods_idfrom zhibo_test.`order`-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by order_id
)
,combine_goods_info as (select combine_goods_id,goods_id_setfrom (select combine_goods_id,goods_id_set,row_number() over(partition by goods_id_setorder by combine_goods_id) as rnfrom (select combine_goods_id,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select combine_goods_id,goods_idfrom zhibo_test.dim_combine_goods-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by combine_goods_id) as a) as awhere rn = 1
)select a.order_id,c.combine_goods_id,b.goods_id
from order_info as a
join zhibo_test.`order` as b
on a.order_id = b.order_id
left join combine_goods_info as c
on a.goods_id_set = c.goods_id_set

主要思想就是,对组合商品维表中的 goods_id_set 进行分区,然后对 combine_goods_id 取 Top1,进行去重。执行后的结果如下:

image-20231207185723063

可以看到,所有订单信息,找到了组合商品,并且没有发生数据膨胀。

下面演示将多个组合商品的信息合并起来的 SQL:

with
order_info as (select order_id-- 这儿使用 collect_set 和 collect_list 效果一样,主要看自己的数据质量,只要是子商品没有重复即可-- 使用 concat_ws 函数将 collect_set 的数组结果拼接起来变成字符串,方便后续的比较。-- 	通过实验,直接使用 collect_set 的数据结果也是可以直接 join 的,但是数组之间是不可以直接使用 = 去判断是否相等的,所以还是转化为字符串这种基本数据类型比较好。,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select order_id,goods_idfrom zhibo_test.`order`-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by order_id
)
,combine_goods_info as (select concat_ws('-', collect_set(combine_goods_id)) as combine_goods_id,goods_id_setfrom (select combine_goods_id,concat_ws('-', collect_set(goods_id)) as goods_id_setfrom (select combine_goods_id,goods_idfrom zhibo_test.dim_combine_goods-- 先对子商品 id 进行排序,再对子商品 id 进行收集和拼接,保证对比时的顺序一致order by goods_id) as agroup by combine_goods_id) as agroup by goods_id_set
)select a.order_id,c.combine_goods_id,b.goods_id
from order_info as a
join zhibo_test.`order` as b
on a.order_id = b.order_id
left join combine_goods_info as c
on a.goods_id_set = c.goods_id_set

主要思想就是将多个组合商品维表中的 goods_id_set 对应的 combine_goods_id 进行合并,变成一条,执行后的结果如下:

image-20231207190214065

可以看到,所有订单信息,找到了组合商品,并且没有发生数据膨胀。

3. 注意

在实际使用中发现,如果夹杂了其他很多处理,整个 SQL 的处理莲路很长,代码中的 order by goods_id 会失效,也就是 concat_ws('-', collect_set(goods_id)) 的结果并不是理想结果,会导致关联时关联不上。

解决方案也很简单,自定义 UDF,输入值为 concat_ws('-', collect_set(goods_id)) 的结果,然后对字符串根据 - 符号拆分成数组,然后在 java 中排序,最后再通过 - 符号拼接,得到处理后的结果,最后再 join 连接,就没问题了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/255958.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

排序:直接选择排序

直接选择排序: 本质: 直接选择排序的本质就是在数组中进行遍历挑选出最大的元素,讲最大的元素放到对应的位置后,再次选出次大的位置,而后又放到对应的位置..........................直到数组成为一个有序序列。 优…

地震反演基础知识3

文章目录 地震勘探原理1 地震波1. 1 地震波概念1. 2 波的传播1. 2. 1 波传播的基本原理1. 2. 2 地震波的反射,折射,透射的1. 2. 3 地震子波(seismic wavelet)1. 2. 4 地震合成记录 2 地震时距曲线2.1 地震时距曲线作用2.2 不同波的时距曲线2.2.1 直达波时…

05 JQuery基础入门

文章目录 一、jQuery介绍1. 简介2. 版本介绍3. 相关网站4. HTML引入方式 二、基础语法1. 顶级对象$2. 与DOM对象转化3. 选择器4. 事件5. 动画6. 修改样式7. 修改属性 一、jQuery介绍 1. 简介 jQuery是JavaScript编程语言底层库,它是一个快速,简洁的Jav…

占用站点资源,无法正常登录?这个功能帮助解决

在企业里随着PDM用户的增加PDM管理员是否发现原本的站点已经不够用出现部分用户占用站点资源导致其他用户无法正常登录导致该问题无法解决,本篇介绍PDM自动下线的功能助力企业解决问题,更好的帮助企业完成PDM的正常使用 今天我给大家带来的就是SOLIDWOR…

Ubuntu 交叉编译工具,执行提示No such file or directory

问题描述 已下载交叉编译工具,并且进行了环境配置。 export PATH/usr/local/arm_linux_4.8/bin/:$PATH使用指令 arm-linux- 加table按键可以看到信息。 但是当查询版本时 arm-linux-gcc -v提示如下: bash: /usr/local/arm_linux_4.8/bin/arm-linux-…

绑定域名简单教程

📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 🌤️安装Nginx环境 &…

12.7 作业

1, #include "widget1.h"Widget1::Widget1(QWidget *parent): QWidget(parent) {//界面设置//修改界面大小this->resize(810,600);//固定界面大小this->setFixedSize(800,600);//修改界面的标题this->setWindowTitle("杰哥和阿伟专场"…

【数据库】基于时间戳的并发访问控制,乐观模式,时间戳替代形式及存在的问题,与封锁模式的对比

使用时间戳的并发控制 ​专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会…

zabbix配置snmp trap--使用snmptrapd和Bash接收器--图文教程

1.前言 我的zabbix的版本是5.0版本,5.0的官方文档没有使用bash接收器的示例,6.0的官方文档有使用bash接收器的示例,但是,下载文件的链接失效?! 这里讲解zabbix-server端配置和zabbix web端配置 2.zabbix-…

数据结构与算法编程题49

假设不带权有向图采用邻接表G存储&#xff0c;设计实现以下功能的算法。 &#xff08;1&#xff09;求出图中每个顶点的出度。 &#xff08;2&#xff09;求出图中出度为0的顶点数。 &#xff08;3&#xff09;求出图中每个顶点的入度。 #include <iostream> using names…

第二十一章

网络通信这一章 基本分为三个部分 网络基础概念和TCP,UDP这三个部分主要如下&#xff1a; 计算机网络实现了堕胎计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是再已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xf…

12.07

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//窗口设置//去掉表头this->setWindowFlags(Qt::FramelessWindowHint);//重新设置大小this->resize(800,420);//设置背景颜色this->setStyleSheet("background-color:whi…