0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

介绍几个Hive常用的函数吧!

电子工程师 来源:lq 2019-02-11 11:32 次阅读

咳咳,今天来介绍一下几个Hive函数吧,先放一张我登哥划水的照片,希望大家也做一只自由的鱼儿,在知识的海洋里游呀游,嘻嘻!

今天我们来介绍几个Hive常用的函数吧!

首先我们产生我们的数据,使用spark sql来产生吧:

valdata=Seq[(String,String)](("{"userid":"1","action":"0#222"}","20180131"),("{"userid":"1","action":"1#223"}","20180131"),("{"userid":"1","action":"2#224"}","20180131"),("{"userid":"1","action":"1#225"}","20180131"),("{"userid":"1","action":"2#225"}","20180131"),("{"userid":"1","action":"0#226"}","20180131"),("{"userid":"1","action":"1#227"}","20180131"),("{"userid":"1","action":"2#228"}","20180131"),("{"userid":"2","action":"0#223"}","20180131"),("{"userid":"2","action":"1#224"}","20180131"),("{"userid":"2","action":"1#225"}","20180131"),("{"userid":"2","action":"2#228"}","20180131")).toDF("info","dt").write.saveAsTable("test.sxw_testRowNumber")

为了模拟我们的hive函数,我们特地将info字段写成了一个json格式,info中有两个键值对,一个是user_id,另一个是用户的行为,行为中有两个数据,用#隔开,分别是动作的类型和动作发生的时间。我们可以这样认为,0代表百度首页,1代表进行了一次搜索的搜索结果页,2代表查看搜索结果中国年的某个详情页。从一次动作0 到 下一次动作0,我们可以认为这是用户和百度一次完整的交互,即一次session,从一次动作1到下一次动作1,可以认为是一次完整的搜索操作。另一个字段是dt,即我们的分区字段。

我们用简单的查询语句来看一下我们的数据效果:

select*fromtest.sxw_testRowNumberwheredt=20180131

结果如下:

get_json_object

我们使用get_json_object来解析json格式字符串里面的内容,格式如下:

get_json_object(字段名,'$.key')

这里,我们来解析info中的userid和action:

selectget_json_object(info,'$.userid')asuser_id,get_json_object(info,'$.action')asactionfromtest.sxw_testRowNumberwheredt=20180131

结果如下:

字符串替换函数

字符串替换函数格式如下:

regexp_replace(字段名,被替换的内容,替换为的内容)

这里我们是可以写正则表达式来替换的,比如我们想把#和数字都替换成大写字母Y:

selectregexp_replace(info,'[\d#]','Y')asinfofromtest.sxw_testRowNumberwheredt=20180131

在上面的语句中,我们用了两个,因为这里需要进行转义。结果为:

字符串切分函数

字符串切分函数split,很像我们javapython中写的那样,格式如下:

split(字段名,分割字符)

split分割后返回一个数组,我们可以用下标取出每个元素。我们把action里面的动作类型和动作时间使用split分割开,语句如下:

selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131

结果如下:

取字串

取字串使用substring方法,格式如下:

substring(字段名,开始位置,提取长度)

这里,如果我们想吧info中前后的大括号去掉,可以使用substring,语句如下:

selectsubstring(info,2,length(info)-2)asinfofromtest.sxw_testRowNumberwheredt=20180131

你可能会问,为什么开始位置是从2开始的而不是1,因为hive中字符串的索引是从1开始的而不是0,同时,我们谁用length方法来计算字符串的长度,结果如下:

有条件计数

有条件计数使用count函数结合case when then语法来实现,比如我们要计算每个用户有多少个session,语句如下:

selectget_json_object(info,'$.userid')asuser_id,count(casewhensplit(get_json_object(info,'$.action'),'#')[0]=='0'then1elsenullend)assession_countfromtest.sxw_testRowNumberwheredt=20180131groupbyget_json_object(info,'$.userid')

结果如下:

上面的几个函数都只是简单的开胃菜,接下来我们来介绍一下重头戏,分组排序函数以及它的两个衍生的函数,row_number() over的格式如下:

row_Number()OVER(partitionby分组字段ORDERBY排序字段排序方式asc/desc)

简单的说,我们使用partition by后面的字段对数据进行分组,在每个组内,使用ORDER BY后面的字段进行排序,并给每条记录增加一个排序序号。比如,我们根据每个用户每条记录的发生时间对用户的行为进行排序,并添加一个序号:

select*row_number()over(partitionbyuser_idorderbyaction_tsasc)astnfrom(selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131)ast

执行结果如下:

可以看到,我们已经成功给用户的行为添加了发生序号。

除了row_number以外,我们还有两个函数,分别是:

lag(字段名,N)over(partitionby分组字段orderby排序字段排序方式)lead(字段名,N)over(partitionby分组字段orderby排序字段排序方式)lag(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式) lead(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)

lag括号里理由两个参数,第一个是字段名,第二个是数量N,这里的意思是,取分组排序之后比该条记录序号小N的对应记录的指定字段的值,如果字段名为ts,N为1,就是取分组排序之后上一条记录的ts值。

lead括号里理由两个参数,第一个是字段名,第二个是数量N,这里的意思是,取分组排序之后比该条记录序号大N的对应记录的对应字段的值,如果字段名为ts,N为1,就是取分组排序之后下一条记录的ts值。

比如,我们用lag和lead分别记录用户上一次行为和下一次行为的发生时间,语句如下:

select*,row_number()over(partitionbyuser_idorderbyaction_tsasc)astn,lag(action_ts,1)over(partitionbyuser_idorderbyaction_tsasc)asprev_ts,lead(action_ts,1)over(partitionbyuser_idorderbyaction_tsasc)asnext_tsfrom(selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131)ast

结果如下:

接下来,我们想实现下面的功能:给每条记录添加一列,该列代表此次session的开始时间。

前面我们介绍过,我们这里认为一次session是从一个action_type为0开始,到下一次action_type为0结束,也就是说,我们这里的数据有三个session,前5条记录是一个session,这五条记录的新列的值应给为222,同理,中间三条记录的新列的值应改为226,而最后四条记录的值应为223,那么如何实现这个功能呢,这就需要我们的lag和lead函数啦。

语句如下:

selectt2.user_id,t2.action_type,t2.action_ts,t1.action_tsassession_tsfrom(select*,lead(action_ts,1)over(partitionbyuser_idorderbyaction_tsasc)asnext_tsfrom(selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131andsplit(get_json_object(info,'$.action'),'#')[0]=='0')ast)t1innerjoin(selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131)t2ont1.user_id=t2.user_idwhere(t2.action_ts>=t1.action_tsandt2.action_ts< t1.next_ts)or ( t2.action_ts >=t1.action_tsandt1.next_tsisnull)

我们来一步步剖析一下该过程的实现,首先,我们在子查询中实现了两个表的内链接。第一个子查询查询出所有session开始的action_ts以及它对应的下一个session开始的action_ts,使用lead实现:

select*,lead(action_ts,1)over(partitionbyuser_idorderbyaction_tsasc)asnext_tsfrom(selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131andsplit(get_json_object(info,'$.action'),'#')[0]=='0')ast

第二个子查询,将简单的进行一下解析:

selectget_json_object(info,'$.userid')asuser_id,split(get_json_object(info,'$.action'),'#')[0]asaction_type,split(get_json_object(info,'$.action'),'#')[1]asaction_tsfromtest.sxw_testRowNumberwheredt=20180131

随后,我们根据两个表的user_id进行内链接,但是内链接之后会多出很多数据,我们要从中取出满足条件的,这里的条件有两个,满足其一即可,即记录的ts在两个session开始的ts之间,要么就没有后一个session:

where(t2.action_ts>=t1.action_tsandt2.action_ts< t1.next_ts)or ( t2.action_ts >=t1.action_tsandt1.next_tsisnull)

最终的结果如下:

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4245

    浏览量

    62058
  • 数组
    +关注

    关注

    1

    文章

    411

    浏览量

    25843

原文标题:来学习几个简单的Hive函数啦

文章出处:【微信号:atleadai,微信公众号:LeadAI OpenLab】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    大数据从业者必知必会的Hive SQL调优技巧

    大数据从业者必知必会的Hive SQL调优技巧 摘要 :在大数据领域中,Hive SQL被广泛应用于数据仓库的数据查询和分析。然而,由于数据量庞大和复杂的查询需求,Hive SQL查询的性能往往
    的头像 发表于 09-24 13:30 70次阅读

    labview中常用的字符串函数有哪些?

    在LabVIEW中,常用的字符串函数广泛覆盖了对字符串的各种操作,包括但不限于格式化、搜索、替换、连接、计算长度等。以下是一些常用的字符串函数及其简要说明: 字符串长度(String
    的头像 发表于 09-04 15:43 185次阅读

    简述socket编程中的常用函数

    Socket编程是一种基于TCP/IP协议的网络编程技术,它允许应用程序通过网络进行通信。在Socket编程中,有许多常用函数,它们用于创建、配置、连接、发送和接收数据等操作。以下是对这些常用
    的头像 发表于 08-16 10:49 174次阅读

    cnn常用几个模型有哪些

    CNN(卷积神经网络)是一种深度学习模型,广泛应用于图像识别、自然语言处理等领域。以下是一些常用的CNN模型: LeNet-5:LeNet-5是最早的卷积神经网络之一,由Yann LeCun等人于
    的头像 发表于 07-11 14:58 356次阅读

    MATLAB信号处理常用函数详解

    MATLAB是一款功能强大的数学软件,尤其在信号处理领域,它提供了众多的函数和工具箱,使得信号的分析、处理、仿真变得简单而高效。本文将详细介绍MATLAB在信号处理中常用函数,并通过
    的头像 发表于 05-17 14:31 1188次阅读

    分享几个嵌入式中常用的GUI

    交互,完成各种操作,可提高工作效率以及用户体验。接下来看一下我们开发中常用的GUI框架有哪些~二、开源轻量级显示框架LVGLLVGL(LightandVersat
    的头像 发表于 04-06 08:09 1227次阅读
    分享<b class='flag-5'>几个</b>嵌入式中<b class='flag-5'>常用</b>的GUI

    典型环节的传递函数介绍

    电子发烧友网站提供《典型环节的传递函数介绍.pdf》资料免费下载
    发表于 03-01 10:28 2次下载

    sumif函数求和的使用方法及实例

    按照上述的语法填写好函数的参数即可。下面,我们通过几个实例来详细介绍Sumif函数的使用方法。 实例一: 假设我们有一个学生成绩表格,
    的头像 发表于 12-03 10:36 1381次阅读

    wps的vlookup函数的使用方法及实例

    WPS Office是一款功能全面的办公软件,其中的VLOOKUP函数在数据分析和处理中非常常用。在本文中,我们将详细介绍WPS Office中VLOOKUP函数的使用方法,并提供一些
    的头像 发表于 12-01 10:58 3382次阅读

    vlookup函数的使用方法

    VLOOKUP函数是Excel电子表格中一种非常常用和有用的函数。它允许用户根据一个特定的查找值,在一个给定的表格中查找匹配的值,并返回这些匹配值所在列的对应数据。这个函数
    的头像 发表于 11-30 17:13 2448次阅读

    HAL库常用函数汇总

    1,系统函数HAL_Delay原型:voidHAL_Delay(uint32_tDelay);作用:利用滴答定时器生成的系统延迟函数参数:Delay:延迟时间,单位是ms返回值:无示例代码
    的头像 发表于 11-29 08:00 2574次阅读
    HAL库<b class='flag-5'>常用</b><b class='flag-5'>函数</b>汇总

    自己编写函数示例代码很难吗?分享几个示例!

    Arduino网站 ,而且他们的示例扩展的效果并不好。本帖将分成以下几个部分:以不包含任何函数的起始代码为例、使用一个函数转换相同的程序、展示可以利用函数做些什么的扩展示例、与没有
    的头像 发表于 11-16 16:05 420次阅读
    自己编写<b class='flag-5'>函数</b>示例代码很难吗?分享<b class='flag-5'>几个</b>示例!

    uC/OS-Ⅱ常用函数查询

    电子发烧友网站提供《uC/OS-Ⅱ常用函数查询.doc》资料免费下载
    发表于 11-03 11:05 0次下载
    uC/OS-Ⅱ<b class='flag-5'>常用</b><b class='flag-5'>函数</b>查询

    EMC常用元件介绍

    电子发烧友网站提供《EMC常用元件介绍.pdf》资料免费下载
    发表于 10-20 16:49 0次下载
    EMC<b class='flag-5'>常用</b>元件<b class='flag-5'>介绍</b>

    认识一下几个常用的门级电路

    标准单元库是数字集成电路的积木,是复杂电路和系统的基础。今天我们来认识一下其中的几个常用门级电路。
    的头像 发表于 10-09 15:49 1193次阅读
    认识一下<b class='flag-5'>几个</b><b class='flag-5'>常用</b>的门级电路