hive行列转置,爆炸函数实例

本文介绍了Hive中的NVL函数用于处理NULL值,CASE WHEN用于条件判断计数,行转列通过CONCAT和CONCAT_WS实现,列转行则通过EXplode和LATERAL VIEW展示。通过实例演示如何在实际场景中应用这些功能。
摘要由CSDN通过智能技术生成

Hive的常用函数(nvl,case when,行转列,列转行,爆炸函数)


综述:

在Hive中有六类常用的函数,除了本文讲述的四类函数之外,还有rank函数,和开窗函数,Hive中的自定义函数一般被分成了三类

UDF:uer-defined-function 一进一出
UDAF:user-defined-aggregation-function 多进一出
UDTF:user-defined-generating-function 一进多出

我们可以通过相关的命令来获取某个函数的用法:

 
  1. show functions 查询所有的自带函数

  2. desc function extended case; 获得例子+用法

  3. desc function case; 获得函数的用法

 NVL:

nvl(value,default_value)如果value为null,则返回default_value的值,否则返回value

 
  1. select comm,nvl(comm,-1) from emp;

  2. 0: jdbc:hive2://hadoop108:10000> select comm,nvl(comm,-1) from emp;

  3. +---------+---------+--+

  4. | comm | _c1 |

  5. +---------+---------+--+

  6. | NULL | -1.0 |

  7. | 300.0 | 300.0 |

  8. | 500.0 | 500.0 |

  9. | NULL | -1.0 |

  10. | 1400.0 | 1400.0 |

  11. | NULL | -1.0 |

  12. | NULL | -1.0 |

  13. | NULL | -1.0 |

  14. | NULL | -1.0 |

  15. | 0.0 | 0.0 |

  16. | NULL | -1.0 |

  17. | NULL | -1.0 |

  18. | NULL | -1.0 |

  19. | NULL | -1.0 |

  20. +---------+---------+--+

  21. 如果员工的comm为NULL,则用领导id代替

  22. select comm,nvl(comm,mgr) from emp;

  23. 0: jdbc:hive2://hadoop108:10000> select comm,nvl(comm,mgr) from emp;

  24. +---------+---------+--+

  25. | comm | _c1 |

  26. +---------+---------+--+

  27. | NULL | 7902.0 |

  28. | 300.0 | 300.0 |

  29. | 500.0 | 500.0 |

  30. | NULL | 7839.0 |

  31. | 1400.0 | 1400.0 |

  32. | NULL | 7839.0 |

  33. | NULL | 7839.0 |

  34. | NULL | 7566.0 |

  35. | NULL | NULL |

  36. | 0.0 | 0.0 |

  37. | NULL | 7788.0 |

  38. | NULL | 7698.0 |

  39. | NULL | 7566.0 |

  40. | NULL | 7782.0 |

  41. +---------+---------+--+

case when:

 
  1. [isea@hadoop108 datas]$ cat emp_sex.txt

  2. 悟空 A 男

  3. 八戒 A 男

  4. 刘备 B 男

  5. 嫦娥 A 女

  6. 大乔 B 女

  7. 小乔 B 女

  8. 需求:求出部门和对应的员工的性别人数

  9. A 2 1

  10. B 1 2

  11. 创建hive表并导入数据:

  12. create table emp_sex(name string,dept_id string,sex string)

  13. row format delimited

  14. fields terminated by '\t';

  15. load data local inpath '/opt/module/datas/emp_sex.txt' into table emp_sex;

  16. 0: jdbc:hive2://hadoop108:10000> select * from emp_sex;

  17. +---------------+------------------+--------------+--+

  18. | emp_sex.name | emp_sex.dept_id | emp_sex.sex |

  19. +---------------+------------------+--------------+--+

  20. | 悟空 | A | 男 |

  21. | 八戒 | A | 男 |

  22. | 刘备 | B | 男 |

  23. | 嫦娥 | A | 女 |

  24. | 大乔 | B | 女 |

  25. | 小乔 | B | 女 |

  26. +---------------+------------------+--------------+--+

  27. > select dept_id,count(sex) from emp_sex group by dept_id;

  28. +----------+------+--+

  29. | dept_id | _c1 |

  30. +----------+------+--+

  31. | A | 3 |

  32. | B | 3 |

  33. +----------+------+--+

  34. 我们来尝试分析一下,如果单纯的使用group by 对dept_id 分组和聚合函数sum,我们求的是部门下所有的

  35. 员工的总数,并不是对于区分性别,所以我们需要一种方式,当检查到sex为男的时候,记录一下man变量为

  36. 1,当检查到sex为女的时候对women 加1

  37. 所以使用下面的查询语句:

  38. select dept_id,sum(case sex when '男' then 1 else 0 end) male_count,

  39. sum(case sex when '女' then 1 else 0 end) female_count

  40. from emp_sex group by dept_id;

  41. +----------+-------------+---------------+--+

  42. | dept_id | male_count | female_count |

  43. +----------+-------------+---------------+--+

  44. | A | 2 | 1 |

  45. | B | 1 | 2 |

  46. +----------+-------------+---------------+--+

  47. 或者使用下面这种功能类似的写法

  48. select dept_id,sum(case when sex = '男' then 1 else 0 end) male_count,

  49. sum(case when sex = '女' then 1 else 0 end) female_count

  50. from emp_sex group by dept_id;

  51. +----------+-------------+---------------+--+

  52. | dept_id | male_count | female_count |

  53. +----------+-------------+---------------+--+

  54. | A | 2 | 1 |

  55. | B | 1 | 2 |

  56. +----------+-------------+---------------+--+

行转列,CONCAT,CONCAT_WS,COLLECT_SET:

什么是行转列呢?

 
  1. 将类似于下面的形式:

  2. A

  3. B

  4. C

  5. 转化为类似于下面的形式:

  6. A B C

  7. 即将多行转化为一行,排在一行了,就成了一列对吧

关于行转列主要有三个函数,

 
  1. concat:

  2. select concat('liubei','xihuan','xiaoqiao');

  3. 0: jdbc:hive2://hadoop108:10000> select concat('liubei','xihuan','xiaoqiao');

  4. OK

  5. +-----------------------+--+

  6. | _c0 |

  7. +-----------------------+--+

  8. | liubeixihuanxiaoqiao |

  9. +-----------------------+--+

  10. concat_ws:

  11. 0: jdbc:hive2://hadoop108:10000> select concat_ws('|',array('liiubei','xihuan','xiaoqiao'));

  12. OK

  13. +--------------------------+--+

  14. | _c0 |

  15. +--------------------------+--+

  16. | liiubei|xihuan|xiaoqiao |

  17. +--------------------------+--+

  18. 1 row selected (0.096 seconds)

  19. collect_set(col)将传入的内容去重,并放置到一个数组中。

  20. [isea@hadoop108 datas]$ cat contellation.txt

  21. 悟空 白羊座 A

  22. 张飞 射手座 A

  23. 刘备 白羊座 B

  24. 八戒 白羊座 A

  25. 小乔 射手座 A

  26. 创建hive表并导入数据:

  27. create table person_info(name string,contellation string,blood_type string)

  28. row format delimited

  29. fields terminated by '\t';

  30. load data local inpath '/opt/module/datas/contellation.txt' into table person_info;

  31. 0: jdbc:hive2://hadoop108:10000> select * from person_info;

  32. OK

  33. +-------------------+---------------------------+-------------------------+--+

  34. | person_info.name | person_info.contellation | person_info.blood_type |

  35. +-------------------+---------------------------+-------------------------+--+

  36. | 悟空 | 白羊座 | A |

  37. | 张飞 | 射手座 | A |

  38. | 刘备 | 白羊座 | B |

  39. | 八戒 | 白羊座 | A |

  40. | 小乔 | 射手座 | A |

  41. +-------------------+---------------------------+-------------------------+--+

  42. 把星座和血型一样的人归类到一起:

  43. t:先将星座和血型归类到一起,

  44. select name,concat(contellation,",",blood_type) base

  45. from person_info;

  46. +-------+--------+--+

  47. | name | base |

  48. +-------+--------+--+

  49. | 悟空 | 白羊座,A |

  50. | 张飞 | 射手座,A |

  51. | 刘备 | 白羊座,B |

  52. | 八戒 | 白羊座,A |

  53. | 小乔 | 射手座,A |

  54. +-------+--------+--+

  55. select t.base,concat_ws('|',collect_set(name)) names

  56. from (

  57. select name,concat(contellation,",",blood_type) base

  58. from person_info

  59. ) t

  60. group by t.base;

  61. +---------+--------+--+

  62. | t.base | names |

  63. +---------+--------+--+

  64. | 射手座,A | 张飞|小乔 |

  65. | 白羊座,A | 悟空|八戒 |

  66. | 白羊座,B | 刘备 |

  67. +---------+--------+--+

  68. 这里使用group by 将base分组,使用collect_set将所有name去重后存放到一个数组中,在使用concat_ws

  69. 将数组中的元素连接起来。

列转行:EXPLODE,LATERAL VIEW:

什么是列转行呢?

 
  1. 把类似于

  2. A , B , C

  3. 转化为

  4. A

  5. B

  6. C

列转行主要有两个函数:

 
  1. select explode(array('liubei','zhangfei','guanyu'));

  2. +-----------+--+

  3. | col |

  4. +-----------+--+

  5. | liubei |

  6. | zhangfei |

  7. | guanyu |

  8. +-----------+--+

  9. select explode(map('liubei','18','zhangfei','19'));

  10. +-----------+--------+--+

  11. | key | value |

  12. +-----------+--------+--+

  13. | liubei | 18 |

  14. | zhangfei | 19 |

  15. +-----------+--------+--+

  16. 来看一下爆炸函数的局限性:在使用爆炸函数的时候,select后面只能跟爆炸函数,其他的不能跟

  17. select '1',explode(array('liubei','zhangfei','guanyu'));

  18. 0: jdbc:hive2://hadoop108:10000> select '1',explode(array('liubei','zhangfei','guanyu'));

  19. FAILED: SemanticException [Error 10081]: UDTF s are not supported outside the SELECT clause, nor nested in expressions

  20. lateral view:斜写视图,为了解决爆炸函数的局限性,结合UDTF函数(如,explode())一起使用。

  21. 将电影分类中的数组数据展开

  22. 期望:

  23. 《疑犯追踪》 悬疑

  24. 《疑犯追踪》 动作

  25. 《疑犯追踪》 科幻

  26. 《疑犯追踪》 剧情

  27. 《Lie to me》 悬疑

  28. 《Lie to me》 警匪

  29. 《Lie to me》 动作

  30. 《Lie to me》 心理

  31. 《Lie to me》 剧情

  32. 《战狼2》 战争

  33. 《战狼2》 动作

  34. 《战狼2》 灾难

  35. [isea@hadoop108 datas]$ cat move_info.txt

  36. 《疑犯追踪》 悬疑,动作,科幻,剧情

  37. 《Lie to me》 悬疑,警匪,动作,心理,剧情

  38. 《战狼2》 战争,动作,灾难

  39. 创建hive表并导入数据:

  40. create table movie_info(name string,category array<string>)

  41. row format delimited

  42. fields terminated by '\t'

  43. collection items terminated by ',';

  44. load data local inpath '/opt/module/datas/move_info.txt' into table movie_info;

  45. 下面使用测写视图的方式,在求出爆炸函数结果的同时,求出除了爆炸函数字段之外的字段。需要添加爆炸之

  46. 后的表名,和爆炸之后的字段名,这个字段名可以放置于select之后,查询爆炸之后的字段值。

  47. select name,category_info

  48. from movie_info

  49. lateral view explode(category) tmp_tbl as category_info;

  50. +--------------+----------------+--+

  51. | name | category_info |

  52. +--------------+----------------+--+

  53. | 《疑犯追踪》 | 悬疑 |

  54. | 《疑犯追踪》 | 动作 |

  55. | 《疑犯追踪》 | 科幻 |

  56. | 《疑犯追踪》 | 剧情 |

  57. | 《Lie to me》 | 悬疑 |

  58. | 《Lie to me》 | 警匪 |

  59. | 《Lie to me》 | 动作 |

  60. | 《Lie to me》 | 心理 |

  61. | 《Lie to me》 | 剧情 |

  62. | 《战狼2》 | 战争 |

  63. | 《战狼2》 | 动作 |

  64. | 《战狼2》 | 灾难 |

  65. +--------------+----------------+--+

  66. 这里需要指出的是:在键表的时候一定不能对于集合数据类型,如果没有添加

  67. collection items terminated by ','表中的数据是这样的:

  68. +------------------+----------------------+--+

  69. | movie_info.name | movie_info.category |

  70. +------------------+----------------------+--+

  71. | 《疑犯追踪》 | ["悬疑,动作,科幻,剧情"] |

  72. | 《Lie to me》 | ["悬疑,警匪,动作,心理,剧情"] |

  73. | 《战狼2》 | ["战争,动作,灾难"] |

  74. +------------------+----------------------+--+

  75. category是一个完整的字符串,也即array中只有一个元素

  76. 添加了分隔符号之后是这样的:

  77. +------------------+-----------------------------+--+

  78. | movie_info.name | movie_info.category |

  79. +------------------+-----------------------------+--+

  80. | 《疑犯追踪》 | ["悬疑","动作","科幻","剧情"] |

  81. | 《Lie to me》 | ["悬疑","警匪","动作","心理","剧情"] |

  82. | 《战狼2》 | ["战争","动作","灾难"] |

  83. +------------------+-----------------------------+--+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值