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.mzph.cn/news/205000.shtml

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

相关文章

Ubuntu宝塔面板本地部署Emlog个人博客网站并远程访问【内网穿透】

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道(云端设置)2.3.Cpolar稳定隧道(本地设置) 3. 公网访问测试总结 前言 博客作为使…

DDoS高防IP到底是什么?

DDoS高防IP是提供一个带防御的IP,主要是针对网络中的DDoS攻击进行保护,是针对互联网服务器遭受大流量的DDoS攻击后,导致服务不可用的情况下,用户可以通过配置高防IP,将攻击流量引流到高防IP上,从而确保源站…

面试华为测试岗,收到offer后我却毫不犹豫拒绝了....

我大学学的是计算机专业,毕业的时候,对于找工作比较迷茫,也不知道当时怎么想的,一头就扎进了一家外包公司,一干就是2年。我想说的是,但凡有点机会,千万别去外包! 在深思熟虑过后&am…

圣诞将至—C语言圣诞树代码来啦

文章目录 圣诞将至—C实现语言圣诞树源码 圣诞将至—C实现语言圣诞树 圣诞树 源码 #define _CRT_SECURE_NO_WARNINGS#include <stdio.h> #include <math.h> #include <stdlib.h> #include <windows.h> #include <time.h> #define PI 3.14159265…

Java网络编程 *TCP与UDP协议*

网络编程 什么是计算机网络? 把分布在不同地理区域的具有独立功能的计算机,通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统 简单来说就是把不同地区的计算机通过设备连接起来,实现不同地区之前的数据传输 网络编程是干什么的? 网络…

GPT 中文提示词技巧:参照 OpenAI 官方教程

前言 搜了半天什么 prompt engineering 的课&#xff0c;最后会发现 gpt 官方其实是有 prompt 教程的。因此本文主要是学习这篇教程。 概述 - OpenAI API 部分案例是参考&#xff1a;根据吴恩达老师教程总结出中文版prompt教程_哔哩哔哩_bilibili up主的内容。 一、尽可能清…

JavaScript实现手写签名,可触屏手写,支持移动端与PC端双端保存

目录 1.HTML模板 2.获取DOM元素和定义变量 3.创建两个canvas元素&#xff0c;并设置它们的宽度和高度 4.绑定触摸事件&#xff1a;touchstart, touchmove, touchend和click 5.实现触摸事件回调函数&#xff1a;startDrawing, draw和stopDrawing 6.实现绘制线段的函数&…

刷题学习记录(文件上传)

[GXYCTF 2019]BabyUpload 知识点&#xff1a;文件上传.htaccessMIME绕过 题目直接给题目标签提示文件上传的类型 思路&#xff1a;先上传.htaccess文件&#xff0c;在上传木马文件&#xff0c;最后蚁剑连接 上传.htaccess文件 再上传一个没有<?的shell 但是要把image/pn…

基于Java SSM框架实现文物管理系统项目【项目源码+论文说明】

基于java的SSM框架实现文物管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…

java设计模式学习之【组合模式】

文章目录 引言组合模式简介定义与用途&#xff1a;实现方式UML 使用场景优势与劣势组合模式在Spring中的应用员工结构示例代码地址 引言 设想您正在组织一个大型派对&#xff0c;需要将各种食品和饮料按类型整理。您可能有单独的物品&#xff0c;如一瓶苏打水&#xff0c;也可…

Qt 如何使用VTK显示点云

开发环境 ubuntu 20.04 VTK 8.2 编译VTK 下载源码 git clone --recursive https://gitlab.kitware.com/vtk/vtk.git 使用版本管理工具&#xff0c;切换版本到8.2 更改编译选项&#xff0c;这里使用cmake-gui进行配置 1、编译类型修改为Release 2、安装路径可以设置&#xf…

JavaScript如何实现按键音效、视频播放,标签分类切换横向滚动

1.使用HTML5的audio标签 &#xff08;音频播放&#xff09; <audio id"click-sound"><source src"audio/show.mp3" type"audio/mpeg"> </audio> <button id"button">按钮</button> var clickSound d…

Vue练习 v-model 指令在状态和表单输入之间创建双向绑定

效果&#xff1a; <template><h2>Text Input</h2><input v-model"text"> {{ text }}<h2>Checkbox</h2><input type"checkbox" id"checkbox" v-model"checked"><label for"checkbox…

使用Notepad++编辑器,安装compare比较差异插件

概述 是一款非常有特色的编辑器&#xff0c;Notepad是开源软件&#xff0c;Notepad中文版可以免费使用。 操作步骤&#xff1a; 1、在工具栏 ->“插件”选项。 2、勾选Compare选项&#xff0c;点击右上角“安装”即可。 3、 确认安装插件 4、下载插件 5、插件已安装 6、打…

服务器配置免密SSH

在当今互联网时代&#xff0c;远程工作和网络安全已成为信息技术领域的热点话题。无论是管理远程服务器、维护网络设备还是简单地从家中连接到办公室&#xff0c;安全始终是首要考虑的因素。这就是为什么 SSH&#xff08;Secure Shell&#xff09;成为了网络专业人士的首选工具…

集合进阶指南:从基础知识到高级应用

集合高级 Collection集合 数组和集合的区别 相同点 都是容器,可以存储多个数据 不同点 数组的长度是不可变的,集合的长度是可变的数组可以存储基本数据类型和引用数据类型 集合只能存储引用数据类型,如果要存基本数据类型,需要存对应的包装类 集合类体系结构 Collectio…

家政预约小程序带商城,图文详解

家政预约小程序开发&#xff0c;在线选择服务分类&#xff0c;选择上门时间&#xff0c;提交订单&#xff0c;在线支付。 商城模块&#xff1a;商品分类&#xff0c;在线下单支付。 个人中心&#xff1a;订单管理&#xff08;家政订单&#xff0c;搬家订单&#xff0c;商品订…

antdesign前端一直加载不出来

antdesign前端一直加载不出来 报错&#xff1a;Module “./querystring” does not exist in container. while loading “./querystring” from webpack/container/reference/mf at mf-va_remoteEntry.js:751:11 解决方案&#xff1a;Error: Module “xxx“ does not exist …

肾虚的16个表现,你有吗?

现代研究发现&#xff1a;导致人体衰老的根本原因不是年龄&#xff0c;而是“肾虚”。此外&#xff0c;肾虚不是男人的专利&#xff0c;女人肾虚的危害更大。 一、肾虚的16个表现 1、总感觉口咸 我们的五味&#xff08;酸苦甘辛咸&#xff09;跟我们的脏腑是相对应的&#xf…

软件设计之装饰模式

装饰模式把每个要装饰的功能放在单独的类中&#xff0c;并让这个类包装它所要装饰的对象&#xff0c;因此&#xff0c;当需要执行特殊行为时&#xff0c;客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。 案例&#xff1a;穿搭。衣柜有帽子、眼镜、…