Hive函数学习之UDTF与UDAF的应用案例

news2024/11/25 18:39:54

UDTF与UDAF的应用案例:

UDTF:一进多出

UDTF是一对多的输入输出,实现UDTF需要完成下面步骤

M1001#xiaohu#S324231212,lkd#M1002#S2543412432,S21312312412#M1003#bfy

1001 xiaohu 324231212

1002 lkd 2543412432

1003 bfy 21312312412

继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,
重写initlizer()、process()、close()。
执行流程如下:

UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息(返回个数,类型)。

初始化完成后,会调用process方法,真正的处理过程在process函数中,在process中,每一次forward()调用产生一行;如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward()函数。

最后close()方法调用,对需要清理的方法进行清理。

“key1:value1,key2:value2,key3:value3”

key1 value1

key2 value2

key3 value3

方法:自定UDTF

字段:id,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12 共13列

数据:

a,1,2,3,4,5,6,7,8,9,10,11,12

b,11,12,13,14,15,16,17,18,19,20,21,22

c,21,22,23,24,25,26,27,28,29,30,31,32

转成3列:id,hours,value

例如:

a,1,2,3,4,5,6,7,8,9,10,11,12

a,0时,1

a,2时,2

a,4时,3

a,6时,4

create table udtfData(
    id string
    ,col1 string
    ,col2 string
    ,col3 string
    ,col4 string
    ,col5 string
    ,col6 string
    ,col7 string
    ,col8 string
    ,col9 string
    ,col10 string
    ,col11 string
    ,col12 string
)row format delimited fields terminated by ',';

代码:

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.util.ArrayList;

public class MyUDTFDemo2 extends GenericUDTF {
    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
        //创建两个集合,这两个集合是一一对应的关系
        //一个是列名的集合
        // 注意集合的泛型
        ArrayList<String> colNameList = new ArrayList<>();
        colNameList.add("id");
        colNameList.add("time");
        colNameList.add("value");
        //另一个是列数据类型的集合
        // 注意集合的泛型
        ArrayList<ObjectInspector> colTypeList = new ArrayList<>();
        colTypeList.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        colTypeList.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        colTypeList.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        //将列名集合和列数据类型集合对应返回
        return ObjectInspectorFactory.getStandardStructObjectInspector(colNameList, colTypeList);
    }

    @Override
    public void process(Object[] args) throws HiveException {
        String[] infos = new String[3];
        //a,1,2,3,4,5,6,7,8,9,10,11,12
        //输出:
        // a  0时  1
        String id = args[0].toString();
        infos[0] = id;
        int t = 0;
        for (int i = 1; i < args.length; i++) {
            infos[1] = t + "时";
            infos[2] = args[i].toString();
            forward(infos);
            t += 2;
        }
    }

    @Override
    public void close() throws HiveException {

    }
}

添加jar资源:

load data local inpath '/usr/local/soft/bigdata30/udtfData.txt' into table udtfData;

add jar /usr/local/soft/bigdata30/data_jars/hive-1.0-jar-with-dependencies.jar;

注册udtf函数:

create temporary function shujia2 as 'com.shujia.custom.udtf.MyUDTFDemo2';

SQL:

select shujia2(*) from udtfData;

在这里插入图片描述

UDAF:多进一出

连续登陆问题

在电商、物流和银行可能经常会遇到这样的需求:统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数等

数据:

注意:每个用户每天可能会有多条记录

id	datestr	  amount
1,2019-02-08,6214.23 
1,2019-02-08,6247.32 
1,2019-02-09,85.63 
1,2019-02-09,967.36 
1,2019-02-10,85.69 
1,2019-02-12,769.85 
1,2019-02-13,943.86 
1,2019-02-14,538.42
1,2019-02-15,369.76
1,2019-02-16,369.76
1,2019-02-18,795.15
1,2019-02-19,715.65
1,2019-02-21,537.71
2,2019-02-08,6214.23 
2,2019-02-08,6247.32 
2,2019-02-09,85.63 
2,2019-02-09,967.36 
2,2019-02-10,85.69 
2,2019-02-12,769.85 
2,2019-02-13,943.86 
2,2019-02-14,943.18
2,2019-02-15,369.76
2,2019-02-18,795.15
2,2019-02-19,715.65
2,2019-02-21,537.71
3,2019-02-08,6214.23 
3,2019-02-08,6247.32 
3,2019-02-09,85.63 
3,2019-02-09,967.36 
3,2019-02-10,85.69 
3,2019-02-12,769.85 
3,2019-02-13,943.86 
3,2019-02-14,276.81
3,2019-02-15,369.76
3,2019-02-16,369.76
3,2019-02-18,795.15
3,2019-02-19,715.65
3,2019-02-21,537.71
建表语句
create table deal_tb(
    id string
    ,datestr string
    ,amount string
)row format delimited fields terminated by ',';

load data local inpath '/usr/local/soft/bigdata30/deal_tb.txt' into table deal_tb;
计算逻辑
  • 先按用户和日期分组求和,使每个用户每天只有一条数据
 select id,datestr,sum(amount) as amount from deal_tb group by id,datestr;
  • 根据用户ID分组按日期排序,将日期和分组序号相减得到连续登陆的开始日期,如果开始日期相同说明连续登陆

  • 统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数

 -- 步骤1 开窗,增添一个按id分组的递增序号列,为后续将日期和分组序号相减得到连续登陆的开始日期做准备
 select 
 t.*,
 row_number() over(partition by t.id order by t.datestr) as rn
 from
 (select id,datestr,sum(amount) as amount from deal_tb group by id,datestr) t;
 
-- 步骤2 根据用户ID分组按日期排序,将日期和分组序号相减得到连续登陆的开始日期,如果开始日期相同说明连续登陆
select 
t2.*,
date_sub(t2.datestr,t2.rn) as grp
from( 
    select 
     t1.*,
     row_number() over(partition by t1.id order by t1.datestr) as rn
     from
     (select id,datestr,sum(amount) as amount from deal_tb group by id,datestr) t1
) t2;

-- 可以使用开窗函数得出最终结果: 统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数
-- 步骤3 直接对t3进行分组:统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间
select 
t3.id as id,
min(t3.datestr) as start_date,
max(t3.datestr) as end_date,
sum(t3.amount) as amounts,
count(1) as days
from
(
    select 
t2.*,
date_sub(t2.datestr,t2.rn) as grp
from( 
    select 
     t1.*,
     row_number() over(partition by t1.id order by t1.datestr) as rn
     from
     (select id,datestr,sum(amount) as amount from deal_tb group by id,datestr) t1
) t2
)t3 group by t3.id,t3.grp;


-- 步骤4 求出间隔天数及最终结果
-- LAG(col,n,default_val):**往前第n行数据,col是列名,n是往上的行数,当第n行为null的时候取default_val 
select 
t4.*,
-- 使用当前行的start_date - 上一行的end_date -1,得出所需要的间隔天数
nvl(datediff(start_date,lag(end_date,1) over(partition by id order by start_date))-1,0) as gap_days
from
(
    select 
    t3.id as id,
    min(t3.datestr) as start_date,
    max(t3.datestr) as end_date,
    sum(t3.amount) as amounts,
    count(1) as days
    from
    (
        select 
    t2.*,
    date_sub(t2.datestr,t2.rn) as grp
    from( 
        select 
         t1.*,
         row_number() over(partition by t1.id order by t1.datestr) as rn
         from
         (select id,datestr,sum(amount) as amount from deal_tb group by id,datestr) t1
    ) t2
    ) t3 group by t3.id,t3.grp
) t4;
  • 结果
    在这里插入图片描述

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

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

相关文章

partially initialized module ‘charset_normalizer‘ has no attribute ‘md__mypyc‘

django项目运行报错&#xff1a; partially initialized module ‘charset_normalizer‘ has no attribute ‘md__mypyc‘…… 解决办法 pip install --force-reinstall charset-normalizer3.1.0

R3CTF 2024 取证部分

TPA 02 - &#x1f4f1; Peggy 是一家公司的员工&#xff0c;和许多人一样&#xff0c;她偶尔也会使用个人手机执行与工作相关的任务。不幸的是&#xff0c;她成为了网络钓鱼攻击的目标。你的任务是找出攻击者的电话号码和佩吉的密码&#xff0c;从而揭露这次攻击的细节。 以…

为什么电容两端电压不能突变

我们先从RC延时电路说起吧&#xff0c;图1是最简单的RC延时电路&#xff0c;给一个阶跃的电压信号&#xff0c;电压会变成黄色曲线这个样子&#xff0c;这是为什么呢&#xff1f; 图1 电压跳变后&#xff0c;电源负极电子移动到电容下极板&#xff0c;排斥上极板电子流动到电源…

Vue集成SpreadJS实现Excel(高级详解)

文章目录 SpreadJS介绍安装 SpreadJS具体使用设置值和公式设置样式绑定数据 更多相关内容可查看 SpreadJS介绍 附官网地址&#xff1a;https://www.grapecity.com.cn/developer/spreadjs 附在线编辑地址&#xff1a;https://demo.grapecity.com.cn/SpreadJS/WebDesigner/inde…

大模型:分本分割模型

目录 一、文本分割 二、BERT文本分割模型 三、部署模型 3.1 下载模型 3.2 安装依赖 3.3 部署模型 3.4 运行服务 四、测试模型 一、文本分割 文本分割是自然语言处理中的一项基础任务&#xff0c;目标是将连续的文本切分成有意义的片段&#xff0c;这些片段可以是句子、…

流量控制和差错控制

流量控制是一种协调发送站和接收站工作步调的技术&#xff0c;其目的是避免由于发送速度过快&#xff0c;使得接收站来不及处理而丢失数据。通常&#xff0c;接收站有一定大小的接收缓冲区&#xff0c;当接收到的数据进入缓冲区后&#xff0c;接收器要进行简单的处理&#xff0…

探索Dagster:现代数据编排的利器

探索Dagster&#xff1a;现代数据编排的利器 在如今数据驱动的世界&#xff0c;数据工程和数据处理的复杂度不断增加&#xff0c;不仅需要管理各种数据源和数据流&#xff0c;还需要确保数据处理管道的可靠性、可维护性和可扩展性。Dagster作为一个现代化的数据编排平台&#x…

java:使用shardingSphere访问mysql的分库分表数据

# 创建分库与分表 创建两个数据库【order_db_1、order_db_2】。 然后在两个数据库下分别创建三个表【orders_1、orders_2、orders_3】。 建表sql请参考&#xff1a; CREATE TABLE orders_1 (id bigint NOT NULL,order_type varchar(255) NULL DEFAULT NULL,customer_id bigi…

运算符和表达式

基本概念 运算符&#xff1a;根据特定的算法对操作数执行运算&#xff0c; 并返回计算结果的符号 操作数&#xff1a;参与运算的对象 表达式&#xff1a;计算的式子 1.算术运算 针对数字&#xff1a;加法。针对字符串&#xff1a;连接。针对复合型数据&#xff1a;合并。…

【需求设计】软件概要设计说明怎么写?概要设计说明书实际项目案例(63页Word直接套用)

软件概要设计说明书书写要点可以归纳为以下几个方面&#xff0c;以确保文档的准确性、完整性和可读性&#xff1a; 引言 目的&#xff1a;介绍编写该文档的目的、主要内容及目标读者。 背景&#xff1a;说明被开发软件的名称、项目提出者、开发者等背景信息。 需求概述&#xf…

【第3章】ComfyUI界面介绍(新增节点的3种方式/主工作区/工作流/设置/插件管理界面)ComfyUI基础入门教程

🥽主界面介绍 ComfyUI的工作界面,我们在上章节中已经见过了(如上所示)。 【注意】大家在网盘下载的comfyui版本,已经内置了很多实用节点,所以跟原始开源版本不一致,不过当前阶段不需要太在意这些。 这里我们快速了解下,界面上的这些区域,都分别是做什么的? 总体…

openGauss 6.0.0 一主二备集群安装及使用zcbus实现Oracle到openGauss的数据同步

一、前言 openGauss 6.0.0-RC1是openGauss 2024年3月发布的创新版本&#xff0c;该版本生命周期为0.5年。根据openGauss官网介绍&#xff0c;6.0.0-RC1与之前的版本特性功能保持兼容,另外&#xff0c;在和之前版本兼容的基础上增加了很多新功能&#xff0c;比如分区表性能优化…

为什么有的网站接口有traceid,有的网站接口没有?

背景&#xff1a;打开百度&#xff0c;输入任意内容&#xff0c;点击百度一下。我们从左侧可以看到有2个接口是有TraceID的 -其他接口是没有的 下面分享我的理解&#xff1a; 对于高并发的业务&#xff08;访问频繁&#xff09;的接口&#xff0c;系统会生成非常多的数据&…

Playwright+Python+Pytest:基础方法二次封装简化及链式调用

引言 随着Web应用的日益复杂化&#xff0c;自动化测试成为了确保软件质量的关键环节。Playwright 是一个强大的自动化库&#xff0c;它支持在 Chromium、Firefox 和 WebKit 中运行自动化脚本。本文将介绍如何使用 Playwright 的 Python 同步 API 来简化点击和填充操作&#xf…

【护网急训2】帕鲁杯应急响应靶场

应急响应靶场 吉祥学安全知识星球&#x1f517;除了包含技术干货&#xff1a;Java代码审计、web安全、应急响应等&#xff0c;还包含了安全中常见的售前护网案例、售前方案、ppt等&#xff0c;同时也有面向学生的网络安全面试、护网面试等。 前段时间更新过一次应急响应靶场&am…

讯飞星火模型-语音转文字实现

目录 项目结构 准备音频 接口Demo 准备代码&#xff08;完整修改后&#xff09; 测试提取中文文字代码 结果 下载链接&#xff1a; 这是上周打算试试&#xff0c;提取视频文字之后&#xff0c;制作视频字幕&#xff0c;从而想用大模型来实现&#xff0c;基本的demo可以在…

Linux和Windows下查看CPU运行频率的方法

文章目录 0.前言1.Linux系统中查看CPU运行频率的方法&#xff08;经测试在UnRaid中适用的&#xff09;1.1.最简单的lscpu命令1.2.查看CPU实时运行频率的watch -n 1 cpufreq-info命令 2.WIndows系统中查看CPU运行频率的方法2.1.系统属性大法2.2.任务管理器大法2.3.CPU-Z等硬件检…

MoneyPrinterPlus:AI自动短视频生成工具,赚钱从来没有这么容易过

这是一个轻松赚钱的项目。 短视频时代&#xff0c;谁掌握了流量谁就掌握了Money! 所以给大家分享这个经过精心打造的MoneyPrinterPlus项目。 它可以&#xff1a;使用AI大模型技术,一键批量生成各类短视频。 它可以&#xff1a;一键混剪短视频&#xff0c;批量生成短视频不是…

计算机网络(3) 字节顺序:网络字节序与IPv4

一.小端与大端 小端&#xff08;Little endian&#xff09;&#xff1a;低字节保存在内存低地址&#xff0c;高字节保存在内存高地址。 大端&#xff08;Big endian&#xff09;&#xff1a;低字节保存在内存高地址&#xff0c;高字节保存在内存低地址。 例如&#xff08;14…

FFmpeg开发笔记(三十四)Linux环境给FFmpeg集成libsrt和librist

《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书的“10.2 FFmpeg推流和拉流”提到直播行业存在RTSP和RTMP两种常见的流媒体协议。除此以外&#xff0c;还有比较两种比较新的流媒体协议&#xff0c;分别是SRT和RIST。 其中SRT全称为Secure Reliable Transport&#xf…