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

本文深入解析Hive SQL中的高级函数应用,包括NVL处理空值、CASE WHEN进行条件判断、行转列与列转行转换技巧,以及如何使用EXPLODE和LATERAL VIEW实现数据结构转换,助你提升数据处理效率。

综述:

 NVL:

case when:

行转列,CONCAT,CONCAT_WS,COLLECT_SET:

列转行:EXPLODE,LATERAL VIEW:


综述:

在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. 《Lie to me》 悬疑
  27. 《Lie to me》 警匪
  28. 《Lie to me》 动作
  29. 《Lie to me》 心理
  30. 《Lie to me》 剧情
  31. 《战狼 2》 战争
  32. 《战狼 2》 动作
  33. 《战狼 2》 灾难
  34. [isea@hadoop108 datas]$ cat move_info.txt
  35. 《疑犯追踪》 悬疑,动作,科幻,剧情
  36. 《Lie to me》 悬疑,警匪,动作,心理,剧情
  37. 《战狼 2》 战争,动作,灾难
  38. 创建hive表并导入数据:
  39. create table movie_info( name string, category array< string>)
  40. row format delimited
  41. fields terminated by '\t'
  42. collection items terminated by ',';
  43. load data local inpath '/opt/module/datas/move_info.txt' into table movie_info;
  44. 下面使用测写视图的方式,在求出爆炸函数结果的同时,求出除了爆炸函数字段之外的字段。需要添加爆炸之
  45. 后的表名,和爆炸之后的字段名,这个字段名可以放置于 select之后,查询爆炸之后的字段值。
  46. select name,category_info
  47. from movie_info
  48. lateral view explode( category) tmp_tbl as category_info;
  49. + --------------+----------------+--+
  50. | name | category_info |
  51. + --------------+----------------+--+
  52. | 《疑犯追踪》 | 悬疑 |
  53. | 《疑犯追踪》 | 动作 |
  54. | 《疑犯追踪》 | 科幻 |
  55. | 《疑犯追踪》 | 剧情 |
  56. | 《Lie to me》 | 悬疑 |
  57. | 《Lie to me》 | 警匪 |
  58. | 《Lie to me》 | 动作 |
  59. | 《Lie to me》 | 心理 |
  60. | 《Lie to me》 | 剧情 |
  61. | 《战狼2》 | 战争 |
  62. | 《战狼2》 | 动作 |
  63. | 《战狼2》 | 灾难 |
  64. + --------------+----------------+--+
  65. 这里需要指出的是:在键表的时候一定不能对于集合数据类型,如果没有添加
  66. collection items terminated by ','表中的数据是这样的:
  67. + ------------------+----------------------+--+
  68. | movie_info.name | movie_info.category |
  69. + ------------------+----------------------+--+
  70. | 《疑犯追踪》 | ["悬疑,动作,科幻,剧情"] |
  71. | 《Lie to me》 | ["悬疑,警匪,动作,心理,剧情"] |
  72. | 《战狼2》 | ["战争,动作,灾难"] |
  73. + ------------------+----------------------+--+
  74. category是一个完整的字符串,也即array中只有一个元素
  75. 添加了分隔符号之后是这样的:
  76. + ------------------+-----------------------------+--+
  77. | movie_info.name | movie_info.category |
  78. + ------------------+-----------------------------+--+
  79. | 《疑犯追踪》 | ["悬疑","动作","科幻","剧情"] |
  80. | 《Lie to me》 | ["悬疑","警匪","动作","心理","剧情"] |
  81. | 《战狼2》 | ["战争","动作","灾难"] |
  82. + ------------------+-----------------------------+--+

 

<think> 首先,用户的问题是基于提供的引用信息,询问Hive中用于行转列转行函数有哪些。引用[1]、[2]和[3]都提到了Hive中的行转列转行操作,但没有具体函数名。 回顾引用: - 引用[1]:提到了转行行转列操作,但没有指定函数。 - 引用[2]:提到了转行行转列和一转多的操作。 - 引用[3]:提到了split函数作为示例,但split不是直接用于行转列转行函数;它用于字符串分割。 根据我的知识,在Hive中: - **行转列(Pivot)**:Hive没有内置的PIVOT函数像SQL Server那样。通常使用CASE WHEN语句来实现行转列。 - **转行(Unpivot)**:可以使用EXPLODE函数或LATERAL VIEW结合UDTF(用户定义表生成函数)来将转为行。 具体函数: - 对于**转行(Unpivot)**:常用函数包括: - `EXPLODE()`:用于数组或映射的展开。 - `POSEXPLODE()`:带位置的explode。 - 结合`LATERAL VIEW`:来处理UDTF。 - 对于**行转列(Pivot)**:Hive原生不支持PIVOT,需要使用聚合函数如SUM、MAX等结合CASE WHEN语句来模拟。 在引用[3]中,提到了split函数,但它不是直接用于行转列/转行的;它用于字符串操作。 用户的问题:"请问hive中用于行转列转行函数有哪些",所以我需要出这些函数。 根据我的知识: - 主要函数: - 转行:`EXPLODE()`, `POSEXPLODE()`, `LATERAL VIEW` - 行转列:没有特定函数,使用`CASE WHEN`和聚合函数。 在Hive中常见的: - `EXPLODE()`:用于将数组或映射转为多行。 - 对于行转列,需要手动写查询。 系统级指令: - 所有行内数学表达式用$...$,但这里可能不涉及数学表达式。 - 独立公式用$$...$$,单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾添加引用标识,如[^1]。 回答结构: - 先回答问题,清晰函数。 - 然后生成相关问题。 - 确保语言是中文。 可能的回答: - 介绍转行函数:`EXPLODE()`、`LATERAL VIEW`。 - 介绍行转列方法:使用`CASE WHEN`语句。 - 引用提供的引用,如果需要的话。用户说"上述引用仅供参考",所以我应该基于我的知识回答,但可以参考引用。 引用提到了split函数在引用[3],但它不是核心函数。我应该专注于核心函数。 生成相关问题: - 系统指令说"生成相关问题",所以在回答末尾添加相关问题。 - 类似示例:"§§相关问题§§",然后出几个问题。 最终回答结构: 1. 开头:直接回答问题。 2. 详细说明:解释每个函数或方法。 3. 添加引用标识:如果需要引用提供的引用。 4. 相关问题。 添加引用:既然用户提供了引用,我应该自然地引用它们。例如,提到引用[2]讨论了具体操作。 但现在,基于查询:"参考站内引用",但实际上引用是针对用户查询的上下文。 用户说:"上述引用仅供参考",所以我使用它们作为参考。 在回答中,可以说:如引用[2]所述,Hive SQL支持行转列转行操作。 具体函数: - 转行:`EXPLODE()` - 行转列:通过CASE WHEN 函数: - 用于转行函数:`EXPLODE()`, `LATERAL VIEW` - 用于行转列函数:没有内置函数,使用SQL构造如聚合和CASE WHEN 在引用中没有指定函数名,所以我会基于标准知识。 </think> 基于您的查询和提供的引用信息,我将详细介绍 Hive 中用于行转列(Pivot)和转行(Unpivot)的核心函数及方法。Hive 作为 Hadoop 生态系统中的数据处理工具,原生支持一些函数来处理这些转换,但部分操作需要结合 SQL 语句实现(如行转列)。以下是详细的函数表和用法说明,结合了我的知识和参考引用中的内容(引用[1]中提到这些操作在数据处理中实用性高[^1],引用[2]强调了一转多的场景[^2],引用[3]则展示了字符串函数如 `split()` 的辅助作用[^3])。 ### Hive 行转列转行函数及方法 在 Hive 中,行转列(将多行数据聚合为单行)和转行(将单行数据展开为多行)是常见的数据处理需求。以下是核心函数和技巧: #### 1. **转行(Unpivot)函数** 转行用于将一或多数据展开为多行记录。主要依赖以下函数: - **`EXPLODE()` 函数**:这是最常用函数,用于将数组(Array)或映射(Map)类型的拆分为多行。语法为 `EXPLODE(array)` 或 `EXPLODE(map)`。 - 示例:假设有一个 `industries` 存储数组 `['IT', 'Finance']`,使用 `EXPLODE(industries)` 可以将它拆分为两行:`'IT'` 和 `'Finance'`。 - 实际应用:常用于处理一多值的场景,如引用[2]中提到的“行业字段含有多个行业”的情况[^2]。 - **`LATERAL VIEW` 语法**:通常与 `EXPLODE()` 结合使用,处理用户定义表生成函数(UDTF)。它将 `EXPLODE()` 的结果作为虚拟表连接回原表。 - 语法:`SELECT ... FROM table LATERAL VIEW EXPLODE(column) alias AS new_column` - 示例:将 `sales` 表中的 `product_list` 数组展开: ```sql SELECT id, exploded_product FROM sales LATERAL VIEW EXPLODE(product_list) exploded_table AS exploded_product; ``` - 优点:支持多展开和复杂嵌套结构。 - **`POSEXPLODE()` 函数**:与 `EXPLODE()` 类似,但额外返回元素的位置索引(position)。适用于需要保留顺序的场景。 - 示例:`SELECT posexplode(industries) AS (pos, industry) FROM table` 这些函数简化了数据展开操作,如引用[1]所述,能帮助高效处理转行需求[^1]。 #### 2. **行转列(Pivot)方法** 行转列用于将多行数据聚合为单行,Hive 没有内置的 PIVOT 函数,需要使用聚合函数(如 `SUM()`, `MAX()`)结合条件语句实现: - **`CASE WHEN` 语句**:这是最常用的方法,通过条件判断将行数据转换为。 - 语法:`SELECT ..., CASE WHEN condition THEN value ELSE default END AS new_column FROM ...` - 示例:将 `sales` 表中不同年份的销售额行数据,转置为(如 `year_2020`, `year_2021`): ```sql SELECT product_id, SUM(CASE WHEN year = 2020 THEN amount ELSE 0 END) AS year_2020, SUM(CASE WHEN year = 2021 THEN amount ELSE 0 END) AS year_2021 FROM sales GROUP BY product_id; ``` - 应用场景:常用于报表生成,如引用[2]中描述的“SQL 行转列和一转多”操作[^2]。 - **辅助函数**:行转列常依赖聚合函数和字符串函数: - `COLLECT_LIST()` 或 `COLLECT_SET()`:将分组后的值收集为数组,可与 `EXPLODE()` 配合用于复杂转换。 - `split()` 函数:虽然不是直接用于行转列,但常用于预处理字符串数据(如引用[3]中的示例 `split('ab_cd_ef', '\_')`[^3]),辅助数据拆分。 #### 关键注意事项 - **性能优化**:转行操作(如 `EXPLODE()`)可能增加数据量,需注意分区和索引以提升效率;行转列操作(`CASE WHEN`)在大型数据集上可能较慢,建议结合聚合优化。 - **兼容性**:这些函数Hive 0.10+ 版本支持。如果数据包含嵌套结构,可以使用 `JSON_TUPLE()` 或其他解析函数预处理。 - **实际案例**:如在引用中所述,这些操作广泛应用于数据清洗、报表生成和行业细分分析[^1][^2]。 如果需要具体代码示例或更多细节,请提供您的数据 schema,我可以生成完整的 Hive SQL 查询。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值