Hive 复杂数据类型

复杂数据类型一共有四种:

  1. ARRAY:数组
  2. MAP:键值对
  3. STRUCT:命名字段集合
  4. UNION:从几种数据类型中指明选择一种,UNION的值必须于这些数据类型之一完全匹配;

     

所用函数说用:

列转行

  1. EXPLODE(col): 将 hive 一列复杂的 array 或者 map 结构拆分成多行。
  2. LATERAL VIEW
    用法:LATERAL VIEW udtf(expression) tableAlias  as columnAlias
    解释:用于和 split,explode 等 UDTF一起使用,它能够将一系列数据拆成多行,在此基础上可以对拆分后的数据进行聚合。

行转列

  1. CONCAT(string A/col, string B/col...):  返回输入字符串连接后的结果,支持任意个输入字符串;
  2. CONCAT_WS(separator,str1,str2,...):  它是一个特殊形式的 CONCAT()。第一个参数剩余参数见的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是NULL,返回值也将为NULL。这个函数会跳过分隔符参数后的任何NULL和空字符串。分隔符将被加到被连接的字符串之间;
  3. COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型的字段。

ARRAY

  1. 创建名为 t2的表,只有 person 和 friends 两个字段, person 是字符串类型, friends 是数组类型,通过文本文件导入数据时,person 和 friends之间的分隔符是竖线,friends 内部的多个元素之间的分隔符是逗号,
    注意分隔符的语法:
     
    create table if not exists t2(
    person string,
    friends array<string>
    )
    row format delimited
    fields terminated by '|'
    collection items terminated by ',';

     

  2. 创建文本文件002.txt, 内容如下:可见只有两条记录,第一条person字段值为 tom,friends字段里面有三个元素,用逗号分隔:
     

    tom|tom_friend_0,tom_friend_1,tom_friend_2
    jerry|jerry_friend_0,jerry_friend_1,jerry_friend_2,jerry_friend_3,jerry_friend_4,jerry_friend_5

     

  3. 执行以下语句,从本地的 002.txt文件导入数据到 t2表:
     

    load data local inpath '/home/hadoop/temp/202010/25/002.txt' into table t2;

     

  4. 查看全部数据:
     

    hive> select * from t2;
    ok
    t2.person t2.friends
    tom ["tom_friend_0","tom_friend_1","tom_friend_2"]
    jerry["jerry_friend_0","jerry_friend_1","jerry_friend_2","jerry_friend_3","jerry_friend_4"]
    

     

  5. 查询friends 中的某个元素的SQL:
     

    select person,friends[0],friend[3] from t2;
    

    执行结果如下,第一条记录没有 friends[3],显示为NULL:

    hive > select person,friends[0],friends[3] from t2;
    OK
    person _c1_c2
    tom    tom_friend_0    NULL
    jerry    jerry_friend_0    jerry_friend_3
    

     

  6. 数组元素中是否包含某值的SQL:
     

    select person, array_contains(friends,'tom_friend_0') from t2;

    执行结果如下,第一条记录 friends数组中有 tom_friend_0 , 显示为 true,第二条记录不包含, 就显示为 false:
     

    hive > select person,array_contains(friends,'tom_friend_0') from t2;
    OK
    person _c1
    tom true
    jerry false
    

     

  7. 第一条记录的friends数组中有三个元素,借助 LATERAL VIEW语法可以把这三个元素 拆成三行,SQL如下:
     

    select t.person,single_friend
    from(
        select person,friends
        from t2 where person='tom'
    ) t LATERAL VIEW explode(t.friends) v as single_friend;

    执行结果如下,可见数组中的每个元素都能拆成单独一行:
     

    OK
    t.person    single_friend
    tom tom_friend_0
    tom tom_friend_1
    tom tom_friend_2
    

    以上就是数组的基本操作,接下来是键值对;
     

MAP,建表,导入数据

  • 接下来打算创建名为 t3 的表, 只有 person 和 address 两个字段, person 是字符串类型, address 是 MAP类型,通过文本文件导入数据时,对分隔符的定义如下:
     
  1. person 和 adress 之间的分隔符 是 竖线;
  2. address内部有多个键值对,他们的分隔符是逗号;
  3. 而每个键值对的键和值的分隔符是冒号;
     
  • 满足上述要求的建表语句如下:
    create table if not exists t3(
    person string,
    address map<string,string>
    )
    row format delimited
    fields terminated by '|'
    collection items terminated by ','
    map keys terminated by ':';

     

  • 创建文本文件 003.txt, 可见用了三种分隔符来 分隔字段、MAP中的多个元素、每个元素键和值:
    tom|province:guangdong,city:shenzhen
    jerry|province:jiangsu,city:nanjing
  • 导入003.txt数据到 t3表:
    load data local inpath '/home/hadoop/temp/202010/25/003.txt' into table t3;

     

MAP ,查询

  1. 查看全部数据:
    hive > select * from t3;
    OK
    t3.person    t3.address
    tom    {"province":"guangdong","city":"shenzhen"}
    jerry    {"province":"jiangsu","city":"nanjing"}
    

     

  2. 查看MAP中某个key,语法是 field["xxx"]:
     

    hive> select person,adress["province"] from t3;
    OK
    person    _c1
    tom    guangdong
    jerry    jiangsu

     

  3. 使用if 函数,下面的SQL是判断 address 字段中是否有 "street"键, 如果有就显示对应的值,没有就显示 field street not exists:
     

    select person,
    if(address['street'] is null,"filed street not exists",address['street'])
    from t3;

    输出如下,由于 address 字段只有 province 和 city 两个键, 因此会显示  filed street not exists:

    OK
    tom filed street not exists
    jerry filed street not exists
        

     

  4. 使用 explode 将 address 字段的每个键值对展示成一行:
     

    hive > select explode(address) from t3;
    OK
    key    value
    province    guangdong
    city    shenzhen
    province    jiangsu
    city    nanjing

     

  5. 上面的explode函数只能展示 address 字段,如果还要展示其他字段就要继续 LATERAL VIEW语法,如下,可见前面的数组展开为一个字段,MAP展开为两个字段,分别是key和value:
     

    select t.person, address_key,address_value
    from(
        select person,address
        from t3 where person='tom'
    ) t LATERAL VIEW explode(t.address) v as address_key,address_value;

    结果如下:

    OK
    t.person    address_key    address_value
    tom    province    guangdong
    tom    city    shenzhen
    

     

  6. size函数可以查看MAP中键值对的数量:
     

    hive> select person,size(address) from t3;
    OK
    tom    2
    jerry    2

     

STRUCT

  1. STRUCT是一种记录类型,它封装了一个命名的字段集合,里面有很多属性,新建名为 t4 的表,其 info字段就是STRUCT类型,里面有 age 和 city 两个属性,person 和 info 之间的分隔符是竖线,info内部的多个元素之间的分隔符是逗号,注意声明分隔符的语法:
    create table if not exists t4(
    person string,
    info struct<age:int,city:string>
    )
    row format delimited
    fields terminated by '|'
    collection items terminated by ',';
  2. 准备好的名为 004.txt的文本文件,内容如下:
    tom|11,shenzhen
    jerry|12,nanjing
  3. 加载 004.txt 的数据到 t4表:
    load data local inpath '/opt/module/hive/temp/004.txt' into table t4;
  4. 查看 t4中的所有数据:
    hive (default)> select * from t4;
    OK
    t4.person       t4.info
    tom     {"age":11,"city":"shenzhen"}
    jerry   {"age":12,"city":"nanjing"}
    Time taken: 0.091 seconds, Fetched: 2 row(s)
    
  5. 查看指定字段,用filedname.xxx语法:
    hive (default)> select person,info.city from t4;
    OK
    person  city
    tom     shenzhen
    jerry   nanjing
    Time taken: 0.085 seconds, Fetched: 2 row(s)

     

UNION

  • 最后一种是 UNIONTYPE, 这是从几种数据类型中指明选择一种,由于UNIONTYPE数据的创建设计到 UDF(create_union),这里先不展开了,先看看建表语句:
    create table union_test(foo UNIONTYPE<int,double,array<string>,struct<a:int,b:string>>);

     

  • 查询结果:
     

上一篇:毕设之旅


下一篇:c-模板运算符的奇怪行为<<