HiveSQL基础Day03

回顾总结

hive表的类型 :内部表和外部表

删除内部表会删除表的所有数据

删除外部表只会删除表的元数据,hdfs上的行数据会保留
表的分区和分桶

本质都是对表数据的拆分存储

分区的方式 是通过创建不同的目录来拆分数据 ,根据数据本身的内容最为目录名

分桶的方式 是通过创建不同的文件来拆分数据 文件名时hash取余的名字


数据拆分后可以提升数据的查询效率


分桶还有特殊使用场景

分桶关联多张表

分桶随机采样
序列化

本质就是对hdfs上的文件数据进行读取和写入

可以通过row format delimited fields terminated by ',' 指定如何读取和写入hdfs上的字段数据

复制代码
CREATE  [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name(
    col_name data_type  [COMMENT col_comment]
  )
  [COMMENT table_comment]
  
  hive中的独有语法
  -- 分区字段指定,分区字段是不能表字段重复
  [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
  -- 分桶字段,需要指定表中存在的字段
  [CLUSTERED BY (col_name, col_name, ...) INTO num_buckets BUCKETS]            
  -- 指定分割符   默认的字段分割符\001
  [ROW FORMAT row_format] 
  -- 指定表的存储目录位置  不指定默认是在对应的数据库目录下创建表目录
  [LOCATION hdfs_path]

一、内置函数

内置函数时hive中自带的函数方法,用来对不同类型的字段数据进行操作

字符串,数值,条件判断

字符串方法

复制代码
length
concat
concat_ws
substr
split
regexp_replace
复制代码
% 
round()
ceil()
floor()
复制代码
if()
​
case 
    when 条件1  then 结果
    when 条件2  then 结果
    when 条件3  then 结果
    else
        前面条件都不成返回的结果
end 字段名称
复制代码
-- 查看hive中的所有内置函数
show functions;
-- 查看函数的具体用户
desc function extended 函数名;

1-1 日期类型操作

复制代码
-- 获取当前日期
select `current_date`();
-- 获取当前日期时间
select `current_timestamp`();
-- 获取unix时间(时间戳) 从1970年1月1号0时0分0秒 到现在过去了多少秒
select unix_timestamp();
​
​
-- unix时间 和日期时间的转化
-- 日期时间转为unix
select unix_timestamp('2023-10-01 15:30:28');
-- 将unix时间转为日期时间
select from_unixtime(12390886789);
​
-- 年月日的取值
select year('2023-10-01 15:30:28');
select month('2023-10-01 15:30:28');
select day('2023-10-01 15:30:28');
select dayofmonth('2023-10-12 15:30:28');
select dayofweek('2023-10-12 15:30:28');
select hour('2023-10-12 15:30:28');
select minute('2023-10-12 15:30:28');
select second('2023-10-12 15:30:28');
​
-- 时间加减
select date_add('2023-10-12 15:30:28',5);
select date_add('2023-10-12 15:30:28',-5);
​
-- 比较时间相差多少天
select datediff(`current_date`(),'2023-10-12');

1-2 类型转化

复制代码
-- 字段类型不符合计算需求,可以进行类型转化
-- 隐式转化  hive会自动判断进行转化数据然后计算
select '123'+'456';
-- 手动指定转化
select cast('123' as int) + cast('456' as int);
​
select * from itcast.tb_hero;
desc itcast.tb_hero;
-- 转化只是在计算时进行,并不会改变字段本身类型
select cast(blood as bigint) from itcast.tb_hero;

1-3 字符串数据转json,array,map操作

  • josn字符串操作

    • 数据是一个 "{key:value}" 格式

    • 使用方法取值value

复制代码
create table tb_order_detail(
    json_field string
);
​
​
select * from tb_order_detail;
-- 对字段中的json字符串数据进行取值,按照key取value值
-- 方法一  get_json_object 每次只能取一个字段数据  ,可以向下一直取值
select
    get_json_object(json_field,'$.orderid') as orderid,
    get_json_object(json_field,'$.total_price') as total_price,
    get_json_object(json_field,'$.total_num') as total_num,
    get_json_object(json_field,'$.goods') as goods,
    get_json_object(json_field,'$.goods[0]') as good1,
    get_json_object(json_field,'$.goods[0].name') as good1_name,
    get_json_object(json_field,'$.goods[1]') as good2
from tb_order_detail;
​
-- json_tuple 一次取多个字段值,不能对嵌套数据往下取值
select json_tuple(json_field,'orderid','total_price','total_num','goods') as(orderid,total_price,total_num,goods) from tb_order_detail
​

将字符串数据切割转为数组数据

复制代码
create table tb_user(
    id int,
    name string,
    hobby string
)row format delimited fields terminated by ',';
​
select id,name,split(hobby,'-') from tb_user;

将字符串数据切割转为map数据

复制代码
-- 使用map方法
select `map`('name','张三','age',29);
​
create table tb_hero(
    id int,
    name string,
    blood int,
    skin string
)row format delimited fields terminated by ',';
-- 西部大镖客:288-大圣娶亲:888-全息碎片:0-至尊宝:888-地狱火:1688 --> {'西部大镖客':288,'大圣娶亲':88}
select id,name,blood,map(split(split(skin,'-')[0],":")[0], cast(split(split(skin,'-')[0],":")[1] as int),split(split(skin,'-')[1],":")[0],cast(split(split(skin,'-')[1],":")[1] as int))from tb_hero;

mysql中的内置函数操作

复制代码
​
select concat(name,sex) from member;
select concat_ws(',',name,sex) from member;
select substr(s_birth,1,4) from student;
select replace(s_birth,'-','/') from student;
select round(3.1421,2);
select round(3.123);
select pow(2,3);
​
​
​
select current_timestamp;
select current_date;
select unix_timestamp();
select unix_timestamp('2023-10-10 10:10:10');
select from_unixtime(127381923);
​
select date_add('2023-10-10 10:10:10',interval 1 day);
select date_add('2023-10-10 10:10:10',interval 1 month );
select date_add('2023-10-10 10:10:10',interval 1 year );
select date_add('2023-10-10 10:10:10',interval -1 year );
select date_add('2023-10-10 10:10:10',interval -1 hour );
​
select timestampdiff(year ,'2020-02-02','2023-02-02');
select timestampdiff(month ,'2020-02-02','2023-02-02');
select timestampdiff(day ,'2020-02-02','2023-02-02');
select timestampdiff(hour ,'2020-02-02 16:23:12','2023-02-02 15:12:12');
​
​
​
​
select if(s_sex='男',1,2),s_sex from student;
select *,
       case
           when year(s_birth) between 1980 and 1989 then '80后'
           when year(s_birth) between 1990 and 1999 then '90后'
        end
from student;

二、DQL的查询计算(掌握)

对表进行查询计算

复制代码
select 字段  from 表;
​
select 字段1,字段2,字段3,常量值,内置函数计算 from tb

2-1 单表查询计算

where 的条件过滤
复制代码
select 字段1,字段2,字段3,常量值,内置函数计算 from tb where 过滤条件

过滤条件,条件成立的将对的行数据返回

  • 比较大小

    • 字段 = 数值 判断字段和数值是否相等

    • 字段 > 数值

    • 字段 < 数值

    • 字段 >= 数值

    • 字段 <= 数值

    • 字段 != 数值

复制代码
-- 大小比较
-- 年龄大于19岁
select * from tb_stu where age >19;
-- 查询性别为女性的学生信息
select * from tb_stu where gender='女';
-- 查询学科不是IS的学生信息
select * from tb_stu where cls !='IS';
  • 判断空值

    • 字段 is null 字段为空

    • 字段 is not null

复制代码
-- 空值判断
insert into tb_stu values(9023,null,'男',20,'MA');
select * from tb_stu where name is not null;
select * from tb_stu where name is null;
​
select * from tb_stu where name !=''; -- 空字符过滤是会将null值一起过滤掉
select * from tb_stu where name =''; -- 相等判断是,空字符是不会过滤出null值的
  • 范围判断

    • 字段 between 数值1 and 数值2

      • 字段 >=数值 and 字段 <=数值
    • 字段 in (数值1,数值2....) 字段的值等于任意一个值就返回结果

复制代码
-- 范围判断
select * from tb_stu where age between 20 and 25;
select * from tb_stu where age in(19,22);
select * from tb_stu where age not in(19,22);
  • 模糊查询

    • 字段 like '% _ 数据' % 可以匹配任意多个 _ 匹配任意一个字符

    • 字段 rlink '正则表达式'

复制代码
​
create table tb_stu2(
    id int,
    name string,
    gender string,
    age int,
    cls string,
    email string
)row format delimited fields terminated by ',';
​
select * from tb_stu2;
-- like的模糊查询
-- 查询姓名为刘的学生
select * from tb_stu where name like '刘%'; -- % 代表任意多个字符
-- 查询姓名为刘的学生 名字个数时2个字的
select * from tb_stu where name like '刘_';
select * from tb_stu where name like '刘__'; -- 查询三个字的
​
-- rlike 的正则表达式
-- 表的是就是通过不同的符号来表示不同的数据进行匹配
-- \\d 匹配数据的表达式   \\w  匹配字符字母  \\s 匹配空格
select * from tb_stu2;
-- ^ 表是什么开头
select * from tb_stu2 where email rlike '^\\d'; -- 表是以数字开头
select * from tb_stu2 where email rlike '^\\w';
select * from tb_stu2 where email rlike '^\\S';
​
-- ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$
​
select email,split(email,'@')[1] from tb_stu2;
select email,split(split(email,'@')[1],'\\.')[0] from tb_stu2;
  • 与或非

    • 条件1 and 条件2 and 条件3 ... 多个条件都成立,返回对应的行数据

    • 条件1 or 条件2 or 条件3 ... 多个条件满足任意一个,返回对应的行数据

复制代码
-- 与 多个条件都成立
select * from  tb_stu;
-- 查询性别为男性,学科是is的
select * from  tb_stu where gender='男' and cls = 'IS';
-- 查询性别为男性或学科是is的
select * from  tb_stu where gender='男' or cls = 'IS';
聚合计算 sum,count
复制代码
select * from tb_stu;
select sum(age) from tb_stu2;
select count(*) from tb_stu where name is not null;
select avg(age) from tb_stu2;
select max(age) from tb_stu;
select min(age) from tb_stu;
分组聚合 group by
复制代码
select sum(age) from tb_stu group by gender;
select sum(age),gender from tb_stu group by gender;

注意分组后,select 中不能出现非分组字段

分组后过滤 having
复制代码
select sum(age),gender from tb_stu group by gender having sum(age)> 200;
排序

order by 全局排序

复制代码
select * from tb_stu order by age; -- 默认是升序 从小到大
select * from tb_stu order by age desc ; -- 降序 从大到小
分页 limit
复制代码
-- 分页
select * from tb_stu limit 5;
select * from tb_stu limit 10,5; -- 页数 m  每页数量是n   (m-1)*n,n

2-2 多表关联查询

join的列关联
  • 内关联

    • 找关联字段相同的数据
  • 左关联

    • 展示保留左边表的所有数据,右边表有相同数据显示,没有相同数据则为null
  • 右关联

    • 展示保留右边表的所有数据,左边表有相同数据显示,没有相同数据则为null
复制代码
-- table1: 员工表
CREATE TABLE employee(
   id int,
   name string,
   deg string,
   salary int,
   dept string
 ) row format delimited
fields terminated by ',';
​
-- table2:员工家庭住址信息表
CREATE TABLE employee_address (
    id int,
    hno string,
    street string,
    city string
) row format delimited
fields terminated by ',';
​
-- table3:员工联系方式信息表
CREATE TABLE employee_connection (
    id int,
    phno string,
    email string
) row format delimited
fields terminated by ',';
复制代码
-- on 当成where使用,进行条件顾虑
select * from employee t1 join  employee_address t2  on  t1.id = t2.id and salary> 30000;
select * from employee t1 left join  employee_address t2  on  t1.id = t2.id;
select * from employee t1 right join  employee_address t2  on  t1.id = t2.id;
-- 实现内关联的效果
select * from employee,employee_address where employee.id = employee_address.id;
union的行关联

将select查询计算后的结果表合并

复制代码
-- union合并
select 'tb_stu',count(*) from tb_stu where name is not null
union
select 'tb_stu2', count(*) from tb_stu2 where name is not null;

-- 保留重复数据
select id,name from tb_stu
union all
select id,name from tb_stu2;

三、窗口聚合

默认没有窗口函数进行计算时全表数据获取计算

根据指定的窗口范围计算数据,将计算结果单独呈现一列展示,不会因为聚合改变行数

复制代码
聚合使用,取值函数,排序函数 over(partition by 分组字段  order by 排序字段  rows between 起始行 and 结束行)
rows 指定计算的行范围

3-1 聚合窗口

复制代码
-- 按照性别分组统计年龄和
select sid,sname,age,gander,province,tuition,sum(age) over(partition by gander) from stu;
select sid,sname,age,gander,province,tuition,sum(age) over(partition by province,gander) from stu;
-- order by 排序后会将前面的数据进行累加
select sid,sname,age,gander,province,tuition,sum(tuition) over(partition by gander order by age) from stu;
select sid,sname,age,gander,province,tuition,avg(tuition) over(partition by gander order by age) from stu;

3-2 取值窗口

复制代码
-- 向上一行取值
select empno,ename,lag(ename) over() from emp;
-- 向上两行行取值
select empno,ename,lag(ename,2) over() from emp;
-- 去不到值给默认值
select empno,ename,lag(ename,2,'itcast') over() from emp;
-- 向下一行取值
select empno,ename,lead(ename) over() from emp;
-- 向下两行行取值
select empno,ename,lead(ename,2) over() from emp;
-- 去不到值给默认值
select empno,ename,lead(ename,2,'itcast') over() from emp;

-- 分组后只进行组内查找
select *,lag(ename) over(partition by job) from emp;

-- 取第一个值
select *,first_value(ename)over(partition by job order by sal desc ) from emp;

3-3 排序窗口

按照指定字段排序后生成序号

复制代码
-- 排序
select *,
       rank() over (order by sal)  as rnk, -- 如果有并列生成序号是不连续的
       dense_rank()  over (order by sal)  as dernk, -- 生成连续序号
       row_number() over (order by sal) as rw -- 生成行号
from emp;

-- 查找薪资前三
select * from (
select *,
       dense_rank()  over (order by sal desc )  as dernk -- 生成连续序号
from emp) tb1
where dernk <=3;
相关推荐
BD_Marathon17 小时前
设置hive本地模式
数据仓库·hive·hadoop
Data 31717 小时前
Hive数仓操作(十一)
大数据·数据库·数据仓库·hive·hadoop
Data 31719 小时前
Hive数仓操作(九)
大数据·数据仓库·hive·hadoop
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑19 小时前
JavaWeb(二)
java·数据仓库·hive·hadoop·maven
Data 3171 天前
Hive数仓操作(三)
大数据·数据库·数据仓库·hive·hadoop
Data 3171 天前
Hive数仓操作(十四)
大数据·数据库·数据仓库·hive·hadoop
Data 3171 天前
Hive数仓操作(十五)
大数据·数据库·数据仓库·hive·hadoop
Data 3171 天前
Hive数仓操作(七)
大数据·数据库·数据仓库·hive·hadoop
Data 3172 天前
Hive数仓操作(四)
大数据·数据库·数据仓库·hive·hadoop
Mephisto.java2 天前
【大数据入门 | Hive】Join语句
数据仓库·hive·hadoop