Hive-DQL(续)及函数

发布时间 2023-06-08 22:53:44作者: FlowersandBoys

Hive--DQL

正则匹配

正则表达式(Regexp)介绍:

概述: ​ 正确的, 符合特定规则的字符串.

Regular Expression

细节:

  1. 正则表达式不独属于任意的一种语言, 市场上大多数的语言都支持正则, 例如: Java, Python, HiveSQL, JavaScript等...

  2. 要求: 能用我们讲的规则, 看懂别人写的 正则表达式(式子)即可. 正则规则:

    ^           代表: 正则开头
    $           代表: 正则结尾
    a           代表: 1个字符a
    .           代表: 任意的1个字符
    \.         代表: 取消.的特殊含义, 即只把它当做1个普通的 点(.)
    \\         代表: 一个 \
    [abc]       代表: a,b,c中的任意1个字符
    [^abc]     代表: 除了a,b,c外的的任意1个字符
    \d         代表: 任意的1个整数, 等价于 [0-9]
    \w         代表: 任意的1个单词字符, 即: 数字, 字母, 下划线, 等价于 [0-9a-zA-Z_]
    \S         代表: 任意的1个非空字符
    ?           代表: 至少0次, 至多1次
    *           代表: 至少0次, 至多n次(无所谓)
    +           代表: 至少1次, 至多n次(无所谓)
    x{n}       代表: x恰好出现 n次(多一次, 少一次都不行)
    x{n,}       代表: x至少出现n次, 至多无所谓.
    x{n,m}     代表: x至少出现n次, 至多m次, 包括n和m

Pay Attention Please

-- 查找手机号符合:188****0*** (四种写法)
select * from orders where userPhone rlike '^188\\S{4}0\\d{3}$';
select * from orders where userPhone rlike '^188\\*{4}0\\d{3}$';
select * from orders where userPhone rlike '^188\\*{4}0[0-9][0-9][0-9]$';       -- 47条
select * from orders where userPhone rlike '^188\\*{4}0[0-9]{3}$';

-- \\d 代表一个\d匹配任意数字, \\* 代表一个特殊的*

联合查询

联合查询解释: 概述: 联合查询指的是 union 查询, 目的: 达到类似于拼接表的操作, 把多张表拼接到一起. 格式: select ... from … union all / distinct select ... from … 细节: 1. 如果直接写union, 后边啥都不写, 默认是: union distinct 2.union all是合并, 但是不去重. union distinct是合并, 但是去重.

  1. 要进行合并的表, 字段个数, 对应`的数据类型必须保持一致.

select * from stu
union all
select * from stu_insert;  -- 联合查询,将两张表放在一块,不去重(注意字段类型一定要匹配,要不会报错

select * from stu
union
select * from stu_insert;  -- 联合查询,这里union 后面没有东西,但是相当于union distinct

select * from stu
union distinct
select * from stu_insert limit 9;  -- 如果在最后面写group by,order by,limit则是作用于整个语句(结果

(select * from stu limit 10)
union
select * from stu_insert;  -- 如果在某个语句后面写group by,order by,limit则是作用于单个语句

随机抽样

随机抽样解释: 概述: 它表示我们通过 tablesample()函数实现, 从大表中抽取出一定的样本数据. 格式: tablesample(bucket x out of y on 列名 或者 rand()); 细节: 1. y表示分成几个桶, 即: 桶的个数. 2. x表示从桶内抽取第x份(条)--将表按照男女分成两个组,第一组必然是女生,第二组必定全部是男 3. 根据列名抽取, 相当于把该列当做了分桶字段抽取, 列名一致的情况下, 其它条件不变(桶的数据等...), 每次抽取到的数据都一样. 4. rand()表示随机数, 即随机抽取, 每次采集到的数据都不一样. 5. x 不能比 y 大.

select * from stu tablesample ( bucket 2 out of 2 on gender);  -- 按照gender将stu表分成两个桶,取第二份
select * from stu tablesample ( bucket 1 out of 2 on rand(2));  -- 随机(以2为种子)将stu表分成两个桶(份,取其中第一份,

虚拟列

虚拟列介绍: 概述: 属于Hive内置的, 数据本身的参数, 辅助我们进行查询的. 分类: INPUT__FILE__NAME 显示数据行所在的 数据文件 BLOCK__OFFSET__INSIDE__FILE 显示数据行所在的 数据文件中的 行偏移量(即: 起始索引) 95001,李勇,男,20,CS 行偏移量(即: 起始索引): 0 95002,刘晨,女,19,IS 行偏移量(即: 起始索引): 23 95003,王敏,女,22,MA 行偏移量(即: 起始索引): 46 ROW__OFFSET__INSIDE__BLOCK 显示数据所在的HDFS块的偏移量, 该虚拟列必须要设置才能用, 即: set hive.exec.rowoffset=true 显示数据行 所在的 Block块的 编号(从 0 开始) 细节:

       1. `1个中文, gbk码表占2个字节, utf-8码表占3个字节`
      2. `row__offset__inside__block`
      3. 就三个内置函数掌握就完事了
select id,INPUT__FILE__NAME from stu;  -- 查看数据行所在的数据文件(file)

select BLOCK__OFFSET__INSIDE__FILE,id from stu;  -- 显示数据行所在文件的偏移量(offset)

set hive.exec.rowoffset=true;  -- 设置开启虚拟列
select *,ROW__OFFSET__INSIDE__BLOCK from stu;  -- 显示数据行所在hdfs块的偏移量,必须设置,而且会报红

Hive函数

Hive函数介绍:

最初Hive函数分为 内置函数 和 用户自定义函数两大类, 其中用户自定义函数又被分为3类, 分别是: ​ 内置函数: 属于Hive自带的. ​ 用户自定义函数: UDF: 全称叫 User Defined Functions, 普通函数, 即: 一进一出. ​ 例如: select * from stu; UDAF: 全称叫 User Defined Aggregation Functions, 聚合函数, 即: 多进一出. ​ 例如: select count(id) from stu; UDTF: 全称叫 User Defined Table-Generating Functions, 表生成函数, 即: 一进多出. ​ 例如: select explode(array(11, 22, 33)); ​ 后来发现用 UDF, UDAF, UDTF来划分Hive函数实在是太方便了, 于是提出了1个词, 叫: 函数标准扩大化, 即: UDF, UDAF, UDTF本来是形容用户自定义函数的, 现在, hive中的函数没有内置函数 和 自定义函数之分了, 取而代之的是: UDF, UDAF, UDTF

Hive官网, 函数解释: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-MathematicalFunctions

Hive函数,必须要掌握的. show functions;

-- 查看hive所有内置函数, 289个, 其中, 符号也是Hive函数一种, 只不过函数名是符号而已. describe function extended 函数名;

-- 查看函数详细信息. split() substr() concat_ws() date_add() datediff() year() round() rand() cast() coalesce() case...when... get_json_object() explode() collect_list() row_number() rank() dense_rank() ntile() lag()

函数忘了咋用?不存在的

show functions ;  -- 查看所有函数

describe function substr;  -- 简单描述函数的信息

describe function extended substr;  -- 详细描述函数的信息(还有例子

字符串相关函数

select substr('abs123',1,3);  -- 提取函数的子串,(字符串,起始位置,子串个数) 效果和substring
select split('12,34,45',',');  -- 将字符串以,进行切割
select concat('12','nihao');  -- 将字符串进行拼接(使用默认方式
select concat_ws('-','12','44');  -- 将字符串以自定义字符方式进行拼接(第一个参数为拼接符
select length('agfa');  -- 获取字符串的长度
select upper('aaaAA');  -- 将字符串转大写
select lower('HAGu');  -- 将字符串转小写
select trim(' hg jhh   ');  -- 移除字符串的首尾空格(字符串中间的空格不用管
select regexp_replace('100-200','\\d+','你好');  -- 将字符串中的数字替换为指定字符
select parse_url('http://www.itcast.cn/path/p1.php?query=1','HOST');  -- 提取url的域名
select parse_url('http://www.itcast.cn/path/p1.php?query=1','QUERY');  -- 提取url的请求
select parse_url('http://www.itcast.cn/path/p1.php?query=1','PATH');  -- 提取url的路径
select parse_url('http://www.itcast.cn/path/p1.php?username=admin01&password=pwd111','QUERY','username')  --提取url中键username的值
select get_json_object('{"name":"小威","age":"18"}','$.name');  -- 获取json字符串中某个对象的值
select get_json_object('[{"name":"小威","age":"18"},{"name":"小李","age":"18"}]','$.[0].name');  -- 获取某个数组中字典某个键的值

日期相关函数

这里有个借助日期函数判断闰年的比较重要嗷

select current_date();  -- 获取当前的日期
select unix_timestamp();  -- 获取当前时间戳
select unix_timestamp('2023-01-23 18:09:23');  -- 获取给定日期的时间戳
select unix_timestamp('2022/01/12','YYYY/mm/dd');  -- 获取给定日期的时间戳,并且指定格式
select from_unixtime(1684500647);  -- 根据指定时间戳获取日期,注意是再加上8小时,因为是东八区时间
select date_add('2023-05-19',2);  -- 日期加2,实际上写-2就是日期减二,也就是说date_sub用不到了
select date_sub('2023-05-19',2);  -- 日期减掉2
select datediff('2023-05-19','2023-05-20');  -- 日期比较 前-后
-- 判断该年是否为闰年 (提示:如果该年是闰年的话,二月有29天,如果不是闰年2月有28天
-- 数学中判断该年是否为闰年的方式是 能被4整除但不能被100整除的年份是闰年,或者能被400整除也是闰年
select dayofmonth(date_add('2022-03-01',-1));  -- 2022年3月1日的前一天是28,所以2022年不是闰年

数字相关函数

select rand();  -- 产生一个0.0-1.0之间的随机数,如果不指定种子seed则随机数一直会不确定
select round('4.1');  -- 取整函数,四舍五入(四舍五入的原理是什么?加0.5取地板数
select floor(4.3+0.5);  -- 取地板数
select ceil(3.4);  -- 取天花板函数
select abs(-23);  -- 取绝对值

非空检验 相关函数

select if(5>3,'郑州','信阳');  -- if条件判断(条件,如果满足,如果不满足
select isnull(null);  -- 非空校验
select isnull('nihao');  -- 判断不为空,结果为false
select isnotnull('nihao'); -- 跟isnull判断结果相反
select nvl(null,'nihao');  -- 判断第一个值是否为空,是空就用第二个,且只能传入2个参数
select coalesce(null,null,'nihao') ; -- coalesce 是合并的意思,从后到前找到第一个不为空的值
select
  case 3
      when 5 then '周五'
      when 3 then '周三'
  end as week;  -- case when 条件判断

杂项函数

-- 类型转换相关.
select cast(10.3 as int);       -- 10
select cast(10 as string);      -- '10'
select cast('12.3' as double);  -- 12.3
select cast('12.3a' as double);  -- null

-- 获取哈希值.
select hash('张三');          -- -838675700
select mask_hash('张三');     -- 1d841bc0ee98309cb7916670b7f0fdef5f4c35150711a41405ef3633b56322cf

-- mask()函数, 脱敏函数, 顺序是: 大写字母, 小写字母, 数字
select mask('abc123ABC');                   -- xxxnnnXXX, 默认: 大写字母X, 小写字母x, 数字n
select mask('abc123ABC', '大','小', '*');     -- xxxnnn***, 指定: 大写字母 大, 小写字母 小, 数字*

-- 对数组元素排序, 默认: 升序.
select sort_array(array(11, 33, 55, 22));       -- [11,22,33,55]

行列转换入门Expolde函数

select explode(champion_year) from the_nba_championship;  -- 爆炸函数,将数组元素炸开
select * from the_nba_championship;
select
      team_name,
      b1.cham_year
from the_nba_championship a1 lateral view explode(champion_year) b1 as cham_year; -- 爆炸函数和侧视图结合

行列转换之: 行转列

select * from row2col2;
select
      col1,
      col2,
      collect_list(col3)  -- collect_list 采集到的数据是数组形式
from row2col2 group by col1,col2;  -- collect_list()采集数据, 可重复, 有序collect_set()采集数据, 唯一, 无序.

select concat_ws('-',1,2,3); -- 这里会报错,因为concat_ws()函数只能拼接字符串
select concat_ws('-',cast(1 as string),cast(2 as string));  -- 可以拼接
select concat_ws('-',array('1','2'));  -- 将数据写成数组形式也可以拼接
select
  col2,
  col1,
  concat_ws('-',collect_list(cast(col3 as string)))
from row2col2 group by col2, col1;  -- 多敲多练,不会也得会

行列转换之: 列转行

create table col2row2(
  col1 string,
  col2 string,
  col3 string
)row format delimited fields terminated by '\t';
select * from col2row2;

select
      a1.col1,
      b1.col_,
      a1.col2
from col2row2 a1 lateral view explode(split(col3,',')) b1 as col_;  -- 注意explode函数只接受map或者array类型的输入

处理json字符串

select get_json_object('{"name":"杨过"}', '$.name');

create table test1_json(
    json string
);
select * from test1_json;
select
    get_json_object(json,'$.device') as device,
    get_json_object(json,'$.deviceType') as deviceType,
    get_json_object(json,'$.signal') as signal,
    get_json_object(json,'$.time') as `time`
from test1_json;  -- 处理json字符串,get_json_object只会处理单个json列

select
       json_tuple(json,'device','deviceType','signal','time')
           as (device, deviceType, signal, `time`)
from test1_json;  -- 写json_tuple 将json关键字扔进去,然后写需要的字段,json_tuple函数会直接提取

select
       device, deviceType, signal, `time`
from test1_json
    lateral view json_tuple(json,'device','deviceType','signal','time') lv
    as device, deviceType, signal, `time`;
-- 通过侧视图将json_tuple 得到的表临时存储为视图,然后定义各个字段的名称,并查询该字段,是上一种写法的变形

create table test2_json(
    device string,
    deviceType string,
    signal string,
    `time` string
)row format serde 'org.apache.hive.hcatalog.data.JsonSerDe' ;
-- 如果不写serde则默认为lazysampleserde处理方式,(row format delimited fields terminated by
select * from test2_json;

CTE表达式

CTE表达式介绍:

概述: 全称叫 Common Table Expression, 公共表表达式, 用来(临时)存储表结果的, 后续可以重复使用. ​ 格式: with CTE表达式的别名 as ( ​ 被CTE所存储的内容, 即: SQL查询语句 ​ ) ​ select ... from cte表达式别名;

-- 1. CTE表达式入门.
with t1 as (
    select * from stu
)
select * from t1;

-- 2. from风格.
with t1 as (
    select * from stu
)
from t1 select name, age;

-- 3. 链式写法(链式编程)
with t1 as (select * from stu),
     t2 as (select * from t1 where id > 95010),
     t3 as (select id, name, gender,age from t2 where id > 95010)
select name, gender from t3;

-- 4. CTE表达式结合 union 使用.
with t1 as (
    select * from stu
)
select * from t1
union  all      -- 合并, 不去重.
select * from t1 limit 3;       -- 44条 => 3条

-- 5. 用表 把 CTE的结果 永久存储.
create table hg1 as
with t1 as (
    select * from stu
)
select id, name, age from t1;

select * from hg1;

-- 6. 用视图 把 CTE的结果 "永久"存储.
create view hg2 as
with t1 as (
    select * from stu
)
select id, name, age from t1;

select * from hg2;