HiveSQL题——collect_set()/collect_list()聚合函数

news2024/11/15 13:39:00

一、collect_set() /collect_list()介绍

       collect_set()函数与collect_list()函数属于高级聚合函数(行转列),将分组中的某列转换成一个数组返回,常与concat_ws()函数连用实现字段拼接效果。

  • collect_list:收集并形成list集合,结果不去重

  • collect_set:收集并形成set集合,结果去重

二、collect_set() /collect_list()有序性

0 问题描述

  有一张用户关注表table20,需求:根据用户user_id分组,按照粉丝关注的时间升序排序,输出粉丝id数组粉丝关注的时间数组,并保障两个数组的数据能一一对应

1 数据准备

create table if not exists table20 (
    user_id int comment '用户id',
    follow_user_id int comment '粉丝id',
    update_time string comment '粉丝关注的时间'
) comment  '用户关注表';

insert overwrite table table20 values
(1, 101,'2021-09-30 10:12:00'),
(1, 103,'2021-10-01 11:00:00'),
(1, 104,'2021-11-02 10:00:00'),
(1, 103,'2021-11-28 10:22:00'),
(2, 104,'2021-11-02 10:11:00'),
(2, 100,'2021-11-03 10:21:00'),
(1, 99,'2021-11-23 12:28:00');

2 数据分析

方式一: row_number() over(partition by .. order by..) as rn 排序,然后再使用collect_list()/collect_set()进行聚合.

select
    user_id,
    concat_ws('|', collect_list(cast(follow_user_id as string))) as fui,
    concat_ws('|', collect_list(update_time))  as ut
      from (select
                user_id,
                follow_user_id,
                update_time,
                row_number() over (partition by user_id order by update_time) rn
            from table20) tmp1
group by user_id;

发现问题:ut数组内的时间并没有按照升序排序输出。

原因分析:

  • HiveSQL执行时,底层转换成MR任务执行,当同时开启多个mapper任务时,mapper1可能处理的user_id是 1,update_time排名为1,2,3的数据,mapper2可能处理的user_id是1,update_time排名为4,5的数据。
  • collect_list()的底层是arrayList 来实现的,当put到arrayList集合时,无法知道是哪个mapper先计算完,所以可能会出现ArrayList集合中的数据顺序与原来数据插入的顺序不对齐的情况。因此:row_number() over(partition by .. order by ..) 与collect_list一起使用的时候,只能是实现局部有序(单个mapper的数据有序),不能实现全局有序。

解决方案:

方案一:使用distribute by + order by

select
    user_id,
    concat_ws('|', collect_list(cast(follow_user_id as string))) as fui_list,
    concat_ws('|', collect_list(update_time))                    as ut_list
from (select
          user_id,
          follow_user_id,
          update_time,
          row_number() over (partition by user_id order by update_time ) as rn
      from (
               select
                   user_id,
                   follow_user_id,
                   update_time
               from table20
                   distribute by user_id sort by update_time
           ) tmp1) tmp2
group by user_id
order by user_id;

 上述代码用到的函数:

(1)concat_ws:带分隔符的字符串连接
   语法: concat_ws(string SEP, string A, string B…)
         select concat_ws('-','abc','def') // abc-def


(2)collect_list:收集并形成list集合,结果不去重
   语法:select id, collect_list(likes) from student group by id;


(2)collect_set:收集并形成set集合,结果去重
   语法:select id, collect_set(likes) from student group by id;

方案二:sort_array(只支持升序)

select
    user_id,
    concat_ws(',', collect_list(cast(follow_user_id as string)))   as fui,
    concat_ws(',', sort_array(collect_list
        (concat_ws('|', lpad(cast(rn as string), 2, '0'), update_time)))) as middle,
    regexp_replace(concat_ws(',', sort_array(collect_list
        (concat_ws('|', lpad(cast(rn as string), 2, '0'), update_time)))), '\\d+\\|', '') as ut
from (select
          user_id,
          follow_user_id,
          update_time,
          rn
      from (
               select
                   user_id,
                   follow_user_id,
                   update_time,
                   row_number() over (partition by user_id order by update_time ) as rn
               from table20
           ) tmp1
      order by rn) tmp2
group by user_id
order by user_id

middle字段值的结果:

ut字段值的结果:

select regexp_replace('04|','\\d+\\|','*')  --> *
正则表达式:\\d+代表所有数字字符

上述代码用到的函数:

(一)lpad / rpad:左/右补足函数
语法:lpad(string str, int len,string pad) / rpad(string str, int len, string pad)
参数说明:
第一个参数:要补齐的字符串
第二个参数:补齐之后字符串的总位数
第三个参数:从左边/右边填充的字符, lpad代表从左边填充;rpad代表从右边填充

举例:
select lpad('abc',5,'fg')  --> fgabc
select rpad('abc',7,'df') --> abcdfdf

因为sort_array 是按照顺序对字符进行排序(例如11会排在2前面),所以可以使用函数lpad补位(将原来的1,2,3,4 转换成 01,02,03,04),然后再正常排序


(二)regexp_replace : 字符串替换
语法:regexp_replace(string initial_string, string pattern, string  replacement)
参数说明:
 initial_string为要替换的字符串,
 pattern为匹配字符串的正则表达式,
 replacement为要替换为的字符串。
简述: regexp_replace (StrA,StrB,StrC) 函数:将字符串A中的符合java正则表达式B的部分替换成C


(三)sort_array : 数组排序函数
 语法:sort_array(array, [asc|desc]) : 按照指定的排序规则对数组进行排序,并返回一个排好序的新数组
 参数说明:
  第一个参数:array为需要排序的数组,
  第二个参数:asc为可选参数,如果设置为true则按升序排序;desc为可选参数,如果设置为true,则按降序排序。如果既不设置asc也不设置desc,则按升序排序

 举例:
select sort_array(array(2, 5, 3, 1)) as sorted_array; ---> [1,2,3,5]
select sort_array(array(2, 5, 3, 1), true, true) as sorted_array; ---> [5,3,2,1]

3 小结

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

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

相关文章

Python 轻量级定时任务调度:APScheduler

简述 APscheduler (Advanced Python Scheduler),作用为按指定的时间规则执行指定的作业。提供了基于日期date、固定时间间隔interval 、以及类似于Linux上的定时任务crontab类型的定时任务。该框架不仅可以添加、删除定时任务,还可以将任务存储到数据库…

【实证分析】地级市-资本存量测算结果数据集(含计算公式及原始数据)( 2003-2021年)

该数据为地级市资本存量测算(2003-2021年),提供了中国地级市在该期间内资本存量的详细测算结果,包括两种基于2011年和2006年基期的测算方式。该数据集利用了从城市统计年鉴和中国统计年鉴获取的固定资产投资数据及其增速&#xff…

布隆过滤器有什么用?什么原理?如何使用?

1 前言 布隆过滤器相信大家没用过的话,也已经听过了。 布隆过滤器主要是为了解决海量数据的存在性问题。对于海量数据中判定某个数据是否存在且容忍轻微误差这一场景(比如缓存穿透、海量数据去重)来说,非常适合。 2 什么是布隆…

docker elasticsearch8启动失败

docker elasticsearch8.12.0启动后提示这个,并且始终无法访问localhost:9200 received plaintext http traffic on an https channel, closing connection Netty4HttpChannel 解决方案:重新创建 elasticsearch容器,加上 -e xpack.security.…

智能边缘计算网关实现高效数据处理与实时响应-天拓四方

在当今时代,数据已经成为驱动业务决策的关键因素。然而,传统的数据处理方式往往存在延迟,无法满足实时性要求。此时,智能边缘计算网关应运而生,它能够将数据处理和分析的能力从中心服务器转移至设备边缘,大…

26条prompt规则应用于大模型

1、引入动机 llm大模型在回答一些问题上表现出了惊人的能力,例如数学逻辑推理,代码生成,问题答复等。提词工程是和大预言模型交流的一门艺术。 大模型的返回结合和用户的指令和输入直接相关prompts是用户和大模型沟通的一种编码方式 一般地…

5+单基因+免疫浸润+单细胞+实验,思路简单易复现

今天给同学们分享一篇生信文章“HOPX is a tumor-suppressive biomarker that corresponds to T cell infiltration in skin cutaneous melanoma”,这篇文章发表在Cancer Cell Int期刊上,影响因子为5.8。 结果解读: 低HOPX表达表明SKCM预后不…

Ai知识图谱

总结:从AI技术栈全貌来看,基础模型、基础算法,个人及小公司是玩不起的,大公司才有对应人力、财力、算力 去做,个人更多的是要在应用场景上创新,几个关键的技术必须会:编码语言(Pytho…

如何使用项目管理工具进行任务分配和进度跟踪

项目管理是一项重要的工作,有效的任务分配和进度跟踪是项目成功的关键因素。 项目经理可以选择合适的项目管理工具来管理项目,在选择项目管理工具时,需要根据项目的特点和需求进行评估。本文将介绍如何使用项目管理工具来进行任务分配和进度…

集成阿里云短信服务

目的是集成阿里云短信服务,完成验证码的发送和接收。 目 录 1、开通阿里云短信服务 2、申请签名 3、申请模板 4、获取AccessKey 5、代码实现 6、代码扩展 7、总结 1、开通阿里云短信服务 去阿里云官网开通 2、申请签名 进行整个步骤时,可以先…

Linux下find命令详解

find #查找文件 #按照文件名、大小、时间、权限、类型、所属者、所属组来搜索文件 格式: find 查找路径 查找条件 具体条件(按文件名或时间大小等) 操作 注意: find命令默认的操作是print输出 find是检索…

浙政钉访接口:k8s+slb容器日志报错(:Temporary failure in name resolution。)

在此我只能说兄弟,浙政钉的扫码接口和用户详情返回这两个接口是不需要白名单的, 我们文明人先确定一件事就是,你代码本地能调用到浙政钉返回。ecs服务器curl浙政钉也通的: 这时候和你说要开通白名单的,请放开你的道德…

2016年苏州大学837复试机试C/C++

2016年苏州大学复试机试 第一题 题目 公鸡5元一只,母鸡3元一只,幼鸡1元3只。若100元钱买了100只鸡,问其中公鸡、母鸡、幼鸡各多少只? 博主注:此题经典百元买百鸡问题,出自:公元5世纪末&#…

Unity 通过配置文件生成代码

文章目录 示例1:基于ScriptableObject的配置生成类示例2:预制体路径列表生成加载代码示例3:动画剪辑生成动画控制器片段示例4:Excel配置表生成序列化类示例5:UI元素及其事件绑定生成代码 在Unity编辑器模式下&#xff…

java并发执行批量插入

java并发执行批量插入 1、mybatis-plus批量插入 long start System.currentTimeMillis();int num 5000; //一次批量插入的数量int j 0;for (int i 0;i<20;i){List<User> userList new ArrayList<>();while (true){j;User user new User();user.setUserP…

美国纳斯达克大屏怎么投放:投放完成需要多长时间-大舍传媒Dashe Media

陕西大舍广告传媒有限公司&#xff08;Shaanxi Dashe Advertising Media Co., Ltd&#xff09;&#xff0c;简称大舍传媒&#xff08;Dashe Media&#xff09;&#xff0c;是纳斯达克在中国区的总代理&#xff08;China General Agent&#xff09;。与纳斯达克合作已经有八年的…

echartstool tips多曲线显示数据处理,保留小数位自定义tooltips样式

位置 options>tooltips>formatter tooltip: {trigger: "axis",axisPointer: {type: "cross",label: {backgroundColor: "#6a7985",},},formatter:(params)>{console.log(params)let str params.forEach((element,index) > {if(ind…

详解SkyWalking前端监控的性能指标

SkyWalking 从8.2.0版本开始支持对前端浏览器端的性能进行监控&#xff0c;不仅可以像以前一样监控浏览器发送给后端服务的与请求&#xff0c;还能看到前端的渲染速度、错误日志等信息——这些信息是获取最终用户体验的最有效指标。实现的方式是引入skywalking-client-js库&…

Jenkins(三):自动化部署SpringBoot项目

前言 在软件开发过程中&#xff0c;自动化部署已经成为不可或缺的一环。Jenkins是一个广泛使用的开源自动化部署工具&#xff0c;它提供了强大的功能和灵活的配置选项&#xff0c;可以帮助开发团队实现高效的持续集成和持续部署。本文将详细介绍如何使用Jenkins自动化部署Spri…

2024/2/3学习记录

微信小程序 小程序中组件的分类 视图容器 view 普通视图区域&#xff0c;类似于 div 常用来实现页面的布局效果。 scroll-view 可滚动的视图区域&#xff0c;常用来实现滚动列表效果 swiper 和 swiper-item 常用 swiper 组件的常用属性 轮播图容器组件和轮播图item组件 基…