Hive专项

Hive专项:数组函数

 

在Hive中,Array是一种用于存储多个相同类型元素的复杂数据结构

Hive中的Array是一种非常实用的复杂数据类型,它能够有效地存储和处理多个相同类型的数据元素。通过使用Array及相关的HiveQL操作函数,人们可以简化数据处理任务,提高查询效率,并在数据分析中实现更多样化的操作。同时,结合其他复杂类型如Map和Struct,Array能提供多层次、多维度的数据组织方式,满足不同业务场景的需求。

  • 灵活性:数组允许存储和处理多个值,适合复杂的数据结构。

  • 高效查询:减少了关联操作,通过数组直接访问和处理数据,提高查询性能。

  • 简化数据模型:使得数据存储更为简洁,适合多值属性和记录。

 

如何构造array

image-20240802161407334

获取数组元素

image-20240802162044273

返回数组中的最大(小)值

image-20240802162512127

  1. array_max(array(1, 3, 5)) c1:创建了一个包含三个元素(1,3,5)的数组,并使用array_max函数找出这个数组中的最大值,即5。然后将这个最大值命名为c1

  2. array_max(array('a', 'b', 'c')) c2:创建了一个包含三个元素('a','b','c')的数组,并使用array_max函数找出这个数组中的最大值,即'c'。然后将这个最大值命名为c2

image-20240802162640788

将数组中的元素连接成一个字符串

  1. array_join(array('1', '3', '5'), '_') c1array_join函数将数组中的元素用指定的分隔符连接起来。这里的数组是['1', '3', '5'],分隔符是'_',所以结果是'1_3_5',并将这个结果命名为c1

  2. concat_ws('#', array('a', 'b', 'c')) c2concat_ws函数也是将多个字符串用指定的分隔符连接起来。这里的字符串是'a', 'b', 'c',分隔符是'#',所以结果是'a#b#c',并将这个结果命名为c2

  3. concat_ws(' ', 'first name', 'last_name') c3:这里的concat_ws函数将'first name''last_name'两个字符串用空格' '连接起来,结果是'first name last_name',并将这个结果命名为c3

 

collect_list/collect set:分组中某列转为数组返回

image-20240802170922720

concat_ws(',', sort_array(collect_list(cast(date AS STRING)))) AS date_concat:这部分是对date字段的处理。首先,cast(date AS STRING)date字段转换为字符串类型。然后,collect_list()函数将同一个user_id下的所有date字段值聚合成一个列表。sort_array()函数将这个列表按照日期的顺序进行排序。最后,concat_ws(',', ...)函数将排序后的日期列表用逗号,连接成一个字符串。

数组包含指定的值array_contains(array, value)

 

 

返回value在数组中的位置 array_position(array, value)

  1. array_position(array(1, 2, 3), 4) c1:这个函数试图在数组[1, 2, 3]中找到值4,但是数组中并没有4,所以返回值为0,然后将这个结果命名为c1。

  2. array_position(array('a', 'b', 'c'), 'a') c2:这个函数在数组['a', 'b', 'c']中找到了值'a','a'在数组中的位置是1,所以返回值为1,然后将这个结果命名为c2。

 

去除数组中的所有value元素 array_remove(array, value)

  1. array_remove(array(1, 2, 3, 2), 2) c1:这个子句创建了一个数组[1, 2, 3, 2],然后使用array_remove函数删除所有值为2的元素。所以,返回的结果将是[1, 3],并将这个结果命名为c1

  2. array_remove(array('a', 'b', 'c'), 'd') c2:这个子句创建了一个数组['a', 'b', 'c'],然后试图删除所有值为'd'的元素。但是,因为原数组中没有'd',所以返回的结果仍然是['a', 'b', 'c'],并将这个结果命名为c2

在数组array1中去除掉所有数组array2中的元素

  1. array_except(array(1, 2, 3, 2), array(2, 3)) c1:这个子句返回的是第一个数组array(1, 2, 3, 2)中存在但第二个数组array(2, 3)中不存在的元素,结果是一个新的数组,这个新的数组被命名为c1

  2. array_except(array('a', 'b', 'c'), array('d')) c2:这个子句返回的是第一个数组array('a', 'b', 'c')中存在但第二个数组array('d')中不存在的元素,结果是一个新的数组,这个新的数组被命名为c2

数组array1和数组array2的交集元素

判断数组为空 size(column) = 0

user_idnameinterestsinterest_status
5Eve[]No interests
4Diana["writing","dancing"]Has interests
3Charlie["gaming","music","art"]Has interests
1Alice["reading","traveling","cooking"]Has interests
2Bob["sports","movies"]Has interests

行转列

lateral view explode

user_data:

user_idnameinterests
5Eve[]
4Diana["writing","dancing"]
3Charlie["gaming","music","art"]
1Alice["reading","traveling","cooking"]
2Bob["sports","movies"]

转换后

user_idnameinterest
3Charliegaming
3Charliemusic
3Charlieart
4Dianawriting
4Dianadancing
1Alicereading
1Alicetraveling
1Alicecooking
2Bobsports
2Bobmovies

 

LATERAL VIEW posexplode

posexplode 是 Hive 中的一个函数,用于将数组或 map 展开为多行,同时保留数组的索引位置

使用 LATERAL VIEW posexplode(features) exploded_table AS pos, featurefeatures 数组展开为多行,同时保留每个特性的索引位置,并将每个特性的索引位置命名为 pos,特性命名为 feature

 

进阶用法

假设我们的表 A 如下:

uidactiontimestamp
1login,view,logout2024-08-01 10:00,2024-08-01 10:30,2024-08-01 11:00
2login,purchase,logout2024-08-02 09:00,2024-08-02 09:15,2024-08-02 09:45
3view,comment,like,logout2024-08-03 08:00,2024-08-03 08:10,2024-08-03 08:20,2024-08-03 08:30

需要转换为

 

将用户的行为和时间戳从字符串形式转换为单独的行,每一行对应一个用户的一个行为和对应的时间戳

  1. 首先,使用WITH语句创建了一个名为A的临时表,包含三个字段:uid(用户ID),action(用户行为,以逗号分隔的字符串),timestamp(行为发生的时间,以逗号分隔的字符串)。

  2. 然后,使用posexplode函数和split函数将actiontimestamp字段中的字符串拆分为多行。posexplode函数会返回一个新的行集,每一行包含一个索引和一个值,索引表示原始字符串中的位置,值表示拆分后的单个元素。split函数用于将字符串按照指定的分隔符(这里是逗号)拆分为多个部分。

  3. LATERAL VIEW是Hive中的一个关键字,用于与posexplode函数一起使用,生成一个虚拟表,这个虚拟表包含了拆分后的索引和值。

  4. FROM A LATERAL VIEW posexplode(split(A.action, ',')) s2 AS idx2, action LATERAL VIEW posexplode(split(A.timestamp, ',')) s3 AS idx3, TIMESTAMP这一行的意思是,对A表中的actiontimestamp字段进行拆分,生成两个虚拟表s2s3s2表包含了action字段拆分后的索引和值,s3表包含了timestamp字段拆分后的索引和值。

  5. WHERE s2.idx2=s3.idx3这一行的意思是,只选择那些actiontimestamp字段拆分后索引相同的行,也就是说,只选择那些行为和时间戳一一对应的行。

最后,这段SQL将返回一个新的表,每一行包含一个用户ID,一个行为和一个时间戳。

Hive专项:CONCAT相关函数

CONCAT

比如:select concat('鲸鲸','说','数据')

return 鲸鲸说数据

CONCAT_WS

image-20240816195935406

比如:select concat_ws(',',array('鲸鲸','说数据'))

return 鲸鲸,说数据

CONCAT_MAP

MAP是啥?

在 Hive 中,MAP 是一种数据结构,用于存储键值对(key-value pairs),类似于 Python 中的字典或 JSON 对象。在 MAP 结构中,每个键都唯一,并且与一个特定的值相关联。

  • 语法:MAP(key1, value1, key2, value2, ...)

  • 例子:SELECT MAP('name', 'Alice', 'age', '30');

使用 MAP 的场景

  • 存储属性信息: 例如,一个 MAP 可以存储一位用户的多个属性信息(如名字、年龄、兴趣爱好等)。

  • 合并信息: 当你有多个信息来源,并且每个来源都有不同的键值对时,可以使用 MAP 来合并这些信息,并保存在一个字段中。

image-20240816200038638

思考

答案

  1. SELECT CONCAT("abc", NULL, "123");

查询解释:

CONCAT 函数将输入的字符串拼接在一起。

如果任何输入为 NULL,则 CONCAT 函数将结果视为 NULL。

答案是NULL

 

  1. SELECT CONCAT_WS(',', array('鲸鲸', '说数据', NULL));

查询解释:

答案是鲸鲸,说数据

 

  1. SELECT CONCAT_MAP(MAP('name', '鲸鲸', 'age', '25'), MAP('hobby', '说数据', 'age', '26'));

查询解释:

答案是{"name": "鲸鲸", "age": "26", "hobby": "说数据"}

MAP 中的 age 键值对被第二个 MAP 中的 age 覆盖,最终的 MAP 包含了所有键值对,age 的值为 26。