全文共454个字,3张图,预计阅读时间5分钟。

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

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

数据介绍

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

val data = 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 * from test.sxw_testRowNumber where dt=20180131

结果如下:

常用的Hive函数get_json_object

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

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

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

select get_json_object(info,'$.userid') as user_id,get_json_object(info,'$.action') as action  from test.sxw_testRowNumberwhere dt=20180131

结果如下:

字符串替换函数

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

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

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

select regexp_replace(info,'[\\d#]','Y') as info  from test.sxw_testRowNumberwhere dt=20180131

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

字符串切分函数

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

split(字段名,分割字符)

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

select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131

结果如下:

取字串

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

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

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

select substring(info,2,length(info)-2) as info  from test.sxw_testRowNumberwhere dt=20180131

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

有条件计数

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

select get_json_object(info,'$.userid') as user_id,count(case  when split(get_json_object(info,'$.action'),'#')[0]=='0' then 1   else null end) as session_count  from test.sxw_testRowNumberwhere dt=20180131group by get_json_object(info,'$.user id')

结果如下:

分组排序函数

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

row_Number() OVER (partition by 分组字段 ORDER BY 排序字段 排序方式asc/desc)

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

select*row_number() over(partition by user_id order by action_ts asc) as tnfrom(select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as  action_ts  from test.sxw_testRowNumberwhere dt=20180131) as t

执行结果如下:

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

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

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

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

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(partition by user_id order by action_ts asc) as tn,lag(action_ts,1) over(partition by user_id order by action_ts asc) as prev_ts,lead(action_ts,1) over(partition by user_id order by action_ts asc) as next_tsfrom(select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131) as t

结果如下:

接下来,我们想实现下面的功能:给每条记录添加一列,该列代表此次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_ts as session_tsfrom(select*,lead(action_ts,1) over(partition by user_id order by action_ts asc) as next_tsfrom(select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131 and split(get_json_object(info,'$.action'),'#')[0] == '0'  ) as t) t1   inner join (select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131 ) t2on t1.user_id = t2.user_idwhere( t2.action_ts >= t1.action_ts    andt2.action_ts < t1.next_ts)or ( t2.action_ts >= t1.action_ts    and t1.next_ts is null)

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

select*,lead(action_ts,1) over(partition by user_id order by action_ts asc) as next_tsfrom(select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131 and split(get_json_object(info,'$.action'),'#')[0] == '0'  ) as t

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

select get_json_object(info,'$.userid') as user_id,split(get_json_object(info,'$.action'),'#')[0] as action_type,split(get_json_object(info,'$.action'),'#')[1] as action_ts  from test.sxw_testRowNumberwhere dt=20180131

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

where( t2.action_ts >= t1.action_ts    andt2.action_ts < t1.next_ts)or ( t2.action_ts >= t1.action_ts    and t1.next_ts is null)

最终的结果如下:

原文链接:https://mp.weixin.qq.com/s?__biz=MzI1MzY0MzE4Mg==&mid=2247483808&idx=1&sn=4bae76c9955a0eef21d1a3afe3358949&chksm=e9d01161dea798771e4b4fbfeb842fd92caaacf4b121cbb2c3fe697c63099590b0abac853360&scene=21#wechat_redirect

查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

www.leadai.org

请关注人工智能LeadAI公众号,查看更多专业文章

大家都在看

LSTM模型在问答系统中的应用

基于TensorFlow的神经网络解决用户流失概览问题

最全常见算法工程师面试题目整理(一)

最全常见算法工程师面试题目整理(二)

TensorFlow从1到2 | 第三章 深度学习革命的开端:卷积神经网络

装饰器 | Python高级编程

今天不如来复习下Python基础

来学习几个简单的Hive函数啦相关推荐

  1. 来学习几个简单的Hive函数吧!

    作者 | 石晓文 转载自小小挖掘机(ID:wAIsjwj) 咳咳,今天来介绍一下几个Hive函数吧,先放一张我登哥划水的照片,希望大家也做一只自由的鱼儿,在知识的海洋里游呀游,嘻嘻! 今天我们来介绍几 ...

  2. 认识Hive,以及Hive的数据定义与数据操作,hive的数据查询和hive函数

    认识Hive 为什么要出现hive 前面知识我们讲到mapreudce计算框架,各位需要通过java编码的形式来实现设计运算过程,这对各位的编程能力提出了更高的要求,难道没有门槛更低的方式来实现运算的 ...

  3. 教你如何运用python实现简单文件读写函数

    这篇文章主要为大家详细介绍了python实现简单文件读写函数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 python作为脚本性语言,加上它的简便易用性.会经常当作脚 ...

  4. Python编程语言学习:sklearn.manifold的TSNE函数的简介、使用方法、代码实现之详细攻略

    Python编程语言学习:sklearn.manifold的TSNE函数的简介.使用方法.代码实现之详细攻略 目录 Manifold简介 TSNE简介-数据降维且可视化 TSNE使用方法 TSNE代码 ...

  5. hive内置函数_flink教程flink modules详解之使用hive函数

    modules概念 通过hive module使用hive函数 内置函数 自定义函数 sql 客户端的使用 原理分析和源码解析 实现 modules概念 flink 提供了一个module的概念,使用 ...

  6. VC学习笔记:简单绘图

    VC学习笔记:简单绘图 SkySeraph Oct.29th 2009  HQU Email-zgzhaobo@gmail.com  QQ-452728574 Latest Modified Date ...

  7. sql自定义函数学习思路_学习SQL:用户定义的函数

    sql自定义函数学习思路 You can create several user-defined objects in a database. One of these is definitely u ...

  8. 强化学习理论基础(MDP、值函数与贝尔曼公式以及表格式Agent)

    强化学习理论基础(MDP.值函数与贝尔曼公式以及表格式Agent) 前言 一.MDP策略与环境模型 二.值函数与贝尔曼公式 1. 值函数 2. 贝尔曼公式 三.表格式Agent 1. 概念介绍 2. ...

  9. OGRE+CG学习日记[1]-简单的3D程序

    OGRE+CG学习日记[1]-简单的3D程序 终于有时间开始研究OGRE和CG这些3D技术方面的东西了 先对今天的成果进行一下简单介绍 ­ 创建一个OGRE窗口,在里面放入一个怪兽头模型 ­ 写一个输 ...

最新文章

  1. ICML2020 | G2Gs:不依赖模板的的逆合成预测新框架
  2. Python自然语言处理工具包推荐
  3. Leetcode: Palindrome Partition I II
  4. Mongo数据库搭建
  5. python生成簇_使用Python复现SIGKDD2017的PAMAE算法(并行kmedoids算法)
  6. 这道小学六年级的数学题,恕我直言没几个人会做
  7. oracle11g安装副武器类,oracle 11g 服务器类
  8. Spring框架 教程
  9. Hive collect、explode函数详解(包括concat、Lateral View)
  10. SmartDNS设置和各个选项意义使用指南
  11. matlab 数据正态性检验
  12. linux 逗号分隔,linux-如何用逗号分割列表而不是sp
  13. [bzoj 2038 OR 清橙A1206 小Z的袜子]莫队算法
  14. JavaScript jQuery修改样式
  15. YTU oj3386
  16. 归结原则_被聘为自由职业者归结为一件事:信任。
  17. css关于图片处理的相关知识
  18. 数字基带调制解调matlab仿真,数字通信系统课程设计--基于MATLAB数字基带调制.doc...
  19. java swing输入框_Java开发笔记(一百二十九)Swing的输入框
  20. 圆通快递 速度奇慢 服务恶劣

热门文章

  1. python属于私有属性_Python私有属性和受保护的属性原理解析
  2. 外卖和快递行业数据_外卖和快递骑手管理“上轨道”
  3. 参会人员管理系统C语言代码,某小型会议参会人员管理系统
  4. 打印设置自定义表尾_如何自定义凭证汇总表打印页面设置
  5. html中如何设置几张图片在一个div里来回切换_从 B 站的秋季主题中学习 “图层组合动画”...
  6. 高中计算机会考选修三知识点,2020高二物理会考知识点总结三篇
  7. 【LOJ】#3030. 「JOISC 2019 Day1」考试
  8. 完美解决xhost +报错: unable to open display 装oracle的时候总是在弹出安装界面的时候出错...
  9. 福大软工1816 · 第二次作业 - 个人项目
  10. 【来自项目的技术点】— 聊聊键盘长按的时候解决卡顿方案