Hive SQL学习笔记

语法顺序

1. 写的顺序 https://blog.csdn.net/dufufd/article/details/103797568

select ... from … join … on ... where ... group by ... having... order by … limit … offset

2. 执行顺序

1) 先运行子查询

2) 每个查询语句里运行顺序

from > join > on > where > group by(开始使用select中的别名,后面的语句中都可以使用) > WITH {CUBE | ROLLUP} > avg,sum.... > having > select > distinct > order by > limit

一、DDL

ddl英文缩写是data definition language(数据定义语言),主要的命令有alter、create、drop、truncate,ddl主要用在定义或者改变表的结构。

1. 创建数据库

create database if not exists 数据库名 location 'hdfs路径';

2. 查询数据库

1)显示数据库

show databases like '包含的字段';

2)显示数据库信息或者数据库详细信息(extended)

desc database extended 数据库名;

3) 切换当前数据库

use 数据库名

3. 修改数据库:ALTER DATABASE命令为某个数据库的DBPROPERTIES设置键-值对属性值

alter database 数据库名

set dbproperties('createtime'='20170830');

4. 删除数据库

1) 删除的数据库

drop database if exists 数据库名;

2)删除不为空的数据库

drop database 数据库名 cascade;

5. 创建表

1)普通创建表

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

[(col_name data_type [COMMENT col_comment], ...)]

[COMMENT table_comment]

[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]

[CLUSTERED BY (col_name, col_name, ...)

[SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]

[ROW FORMAT row_format]

[STORED AS file_format]

[LOCATION hdfs_path]

[TBLPROPERTIES (property_name=property_value, ...)]

[AS select_statement]

EXTERNAL是外部表的关键字

COMMENT:为表和列添加注释

PARTITIONED BY创建分区表

CLUSTERED BY创建分桶表

SORTED BY不常用,对桶中的一个或多个列另外排序

ROW FORMAT

    row format delimited fields terminated by ',' -- 列分隔符

    collection items terminated by '_' --MAP STRUCT ARRAY 的分隔符(数据分割符号)

    map keys terminated by ':' -- MAP中的keyvalue的分隔符

    lines terminated by '\n'; -- 行分隔符

STORED AS指定存储文件类型

LOCATION :指定表在HDFS上的存储位置。

AS:后跟查询语句,根据查询结果创建表。

LIKE允许用户复制现的表结构,但是不复制数据。

2)根据查询结果创建表(查询的结果会添加到新创建的表中)

create table if not exists 新表名 [select statement];

3) 根据已经存在的表结构创建表

create table if not exists 新表名 like 旧表名;

6. 查询表

1)查看创建的表

show tables

2) 查询表的类型

desc formatted 表名;

3) 查询表的结构

desc 表名

7. 管理表与外部表的互相转换 => True为外部表; False为内部表

alter table 表名 set tblproperties('EXTERNAL'='TRUE');

注意:('EXTERNAL'='TRUE')('EXTERNAL'='FALSE')为固定写法,区分大小写!

8. 修改表

1) 修改表名

ALTER TABLE 旧表名 RENAME TO 新表名

2) 增加列

alter table 表名 add columns(新列名 列类型 [COMMENT col_comment]);

     3) 更新列

alter table 表名 change column 旧表名 新表名 列类型 column_type [COMMENT col_comment] [FIRST|AFTER column_name];

注意:小(int)的往大(string)的改(反过来不可以【语法不支持只改列名,但是类型改之前和之后一样】

隐式类型转换规则如下

①任何整数类型都可以隐式地转换为一个范围更广的类型,如TINYINT可以转换成INTINT可以转换成BIGINT

②所整数类型、FLOATSTRING类型都可以隐式地转换成DOUBLE

TINYINTSMALLINTINT都可以转换为FLOAT

BOOLEAN类型不可以转换为任何其它的类型

4) 替换列

alter table 表名 replace columns(列名1 列类型, 列名2, 列类型);

注:ADD是代表新增一字段,字段位置在所列后面(partition列前)REPLACE则是表示替换表中所字段。

二、DML

dml英文缩写是data manipulation language(数据操纵语言),主要的命令有select、update、delete、insert,dml主要用来操作数据库中的数据

1. 数据导入

1) 向表中装在数据(load)

① 加载本地文件到hive (本地存在这张表) load会修改原数据】

     load data local inpath '本地路径' into table default.表名 partition(字段='分区规则')partition(day='yyyy-mm-dd', hour='hh');

② 加载HDFS文件到hive / 加载数据覆盖表中已的数据(HDFS上要有这个表, 没有需要上传)

 dfs -put 本地绝对路径 HDFS绝对路径;

     load data inpath 'hdfs绝对路径' overwrite into table default.表名;

注意:overwrite为可选关键词, 表示载数据覆盖表中已的数据

2) 通过查询语句向表中插入数据(Insert)

基本插入数据 (多个值用逗号隔开)

insert into table 表名 values(1,'wangwu'),(2,'zhaoliu');

基本模式插入(根据单张表查询结果)

insert overwrite table 表名

[select 列名 from 表名 where 条件]

insert into:以追加数据的方式插入到表或分区,原数据不会删除         

insert overwrite:会覆盖表中已存在的数据

注意:insert不支持插入部分字段

单表指的是最终接受表的是单表, 而查询的表可以多表(join)

多表(多分区插入模式(根据多张表查询结果)

from student

insert overwrite table student partition(month='201707')

select id, name where month='201709'

insert overwrite table student partition(month='201706')

select id, name where month='201709';

查询语句中创建表并加载数据(As Select) # create table后面不用加字段和类型

create table if not exists 新表名

as [select statement];

创建表时通过Location指定加载数据路径

1) 上传数据到hdfs上(先在hdfs创建目录,然后将本地数据上传到该目录)

dfs -mkdir /hdfs目录名;

dfs -put 本地数据绝对路径 /hdfs目录名;

2) 创建表,并指定在hdfs上创建目录的的位置

create external table if not exists 新表名(

列名1 数据类型, 列名2 数据类型

)

row format delimited fields terminated by '分隔符'

location 'hdfs目录';

注意:创建表格默认路径在/user/hive/warehouse, 如果不写location, 就默认在这个路径

3) 查询数据

select * from student5;

⑥ Import 数据到指定 Hive 表中

。 (路径是export导出路径,否则invalid path)

2. 数据导出

1) insert 导出

将查询的结果【格式化:row format】导出到本地 【导出到HDFS(local关键字)

insert overwrite local directory '本地绝对路径/HDFS绝对路径'

ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符'

select * from 表名;

2) Hadoop 命令导出到本地 (表名不能同名)

dfs -get /user/hive/warehouse/student/student.txt

/opt/module/data/export/student3.txt;

3) Hive Shell 命令导出 (>写入到file里并打印出来, >>写入到file不打印出来)

bin/hive -f/-e '执行语句或者脚本'>  写入file绝对路径

bin/hive -f/-e '执行语句或者脚本'>>  写入file绝对路径

     4) Export 导出到 HDFS 上 (export import一起使用主要用于两个 Hadoop 平台集群之间 Hive 表迁移。

export table 数据库.表名 to 'hdfs绝对路径;

注意:如果hdfs没有某个路径, export会在hdfs创建这个路径; 这个路径和普通路径区别在于多导出了原数据信息

import table 表名 'hdfs绝对路径'

import导入数据的要求包括:

① import输入数据必须是export导出的路径

② 写入数据的表不存在,或者存在但没数据(空表)

     5) Sqoop导出

3. 清除表中数据(Truncate)

    truncate table 表名;

注意:Truncate 只能删除管理表(删除表中数据,表还在),不能删除外部表中数据

三、DCL

dcl英文缩写是 data control language(数据控制语言),主要的命令有grant、deny、revoke等,dcl主要用来设置或者更新数据库用户或者角色权限

四、TCL

tcl英文缩写是 Transaction Control language,主要的作用是用来控制事务的,常用的关键字有commit、rollback、setpoint等

五、排序

1. order by (一个reducer)

2. sort by & distribute by

1) 先设置reducer个数

set mapreduce.job.reduces=3;

2) 查询语句写到本地分区路径

insert overwrite local directory '本地分区绝对路径' select * from 表名 distribute by 分区字段 sort by 排序字段 desc/asc;

3. cluster by (分区&排序字段相同; 必须升序)

select * from 表名 cluster by 分区&排序字段;

select * from 表名 distribute by 分区字段 sort by 排序字段;

六、分区 (避免全表扫描)

1. 静态分区

1) 创建分区表(包括一级、二级)

create table 表名_partition(

列名1 类型, 列名2 类型

partitioned by (day string, hour string)

row format delimited fields terminated by '\t';

注意:分区字段不能是表中已经存在的数据,可以将分区字段看作表的伪列。

2) 加载数据

load data local inpath '分区表本地绝对路径' into table 表名_partition partition(day='', hour='');

3) 查询分区数据

select * from 表名_partition where day=''and hour='';

4) 增加分区 (多个分区用空格) (二级分区多了一个子目录)

alter table 表名_partition add partition(day='') partition(day='');

5) 删除分区 (多个分区用逗号)

alter table 表名_partition drop partition (day=''),partition(day='');

6) 查询分区表结构

show partitions 表名_partition;

7) 查询分区表有多少分区

desc formatted 表名_partition;

8) 将数据用hdfs命令直接上传到hdfs的分区目录上, 本地原数据是看不到分区目录和数据, 三种方式解决:

dfs -mkdir -p /user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=13;

dfs -put /opt/module/datas/dept_20200401.log /user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=13;

① 执行修复命令

msck repair table dept_partition2;

② 添加分区

alter table dept_partition2 add partition(day='201709',hour='14');

③ 创建文件夹后load数据到分区

load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table dept_partition2 partition(day='20200401',hour='15');

注意: 如果不加分区字段, 会报错;不指定分区就会走MR, , hive默认走yarn, yarn把任务提交到resource manager, MR是由resource manager随机选个机器执行, 找个有数据的机器执行就不会报错, 但是没有数据的机器执行就会报错;通过分发数据目录到各个集群, 所有机器都有数据,因此就不会报错。

2. 动态分区

1) 创建目标分区表 # 分区字段和table里面数据不一样

create table dept_partition_dy(id int, name string)

partitioned by (loc int)

row format delimited fields terminated by '\t';

2) 设置动态分区

set hive.exec.dynamic.partition.mode = nonstrict;

insert into table dept_partition_dy partition(loc)

select deptno, dname, loc from dept;

注意:默认按select语句最后一个字段分区并且创建表格的二级分区顺序partitioned by (day string, hour string) select最后两个字段顺序保持一致day, hourhive3.0版本可以省略partition(loc)不用指定动态分区模式, 不会报错, strict也可以, 因为内部转为nonstrict

七、分桶表

# 分桶字段和table里面数据不一样

1. 创建分桶表 (指定分桶字段和个数)

create table stu_buck(id int, name string)

clustered by(id)

into 4 buckets

row format delimited fields terminated by '\t';

2. 导入数据到分桶表中 (MR)

load data inpath'/student.txt' into table stu_buck;

八、函数分类

UDF: 一进一出 【CONCAT_WS(separator, str1, str2,...) - 多列变一列】

UDAF: 多进一出

UDTF: 一进多出 【lateral view EXPLODE(col) 一行(arraymap结构)变多行】

多指的是输入数据的行数.

比如:

将一个单元格的多个文字, split函数变成一个数组

select split(category,',') from movie_into

["悬疑, "动作" , 科幻" ,"剧情" ]

["悬疑""警匪", "动作","心理" ,"剧情" ]

["战争", "动作", "灾难]

如果只需要炸裂一列, 不需要与原数据列做关联

select explode(split(category,',')) from movie_into

 电影只行, 炸卡的列数多比较多, 用侧写lateral view 就会关联在一起movie_info_tmp 炸裂字段和原表字段关联

 SELECT

 movie,

 category_name

 FROM

 movie_info

 lateral VIEW

 explode(split(category,",")) movie_info_tmp  AS category_name;

查看函数用法

desc function 函数名

九、窗口函数

关键字:

CURRENT ROW:当前行

nPRECEDING:往前n行数据

nFOLLOWING:往后n行数据

UNBOUNDED:起点,

UNBOUNDED PRECEDING 表示从前面的起点,

UNBOUNDEDFOLLOWING表示到后面的终点

LAG(col,n,default_val):往前第n行数据

LEAD(col,n,default_val):往后第n行数据

NTILE(n):把序窗口的行分发到指定数据的组中,各个组编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

应用举例:

jack,2017-01-01,10

tony,2017-01-02,15

jack,2017-02-03,23

tony,2017-01-04,29

jack,2017-01-05,46

jack,2017-04-06,42

tony,2017-01-07,50

jack,2017-01-08,55

mart,2017-04-08,62

mart,2017-04-09,68

neil,2017-05-10,12

mart,2017-04-11,75

neil,2017-06-12,80

mart,2017-04-13,94

创建表格

create table business(

name string,

orderdate string,
    cost int

) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

load data local inpath "/opt/module/data/business.txt" into table business;

1. (over代表开窗范围)

1) 查询在20174月份购买过的顾客及总人数

select name,count(*) over () from business

where substring(orderdate,1,7) = '2017-04' group by name;

2) 查询顾客的购买明细及顾客月购买总额

select name,orderdate,cost,sum(cost) over(partition by name, month(orderdate)) from business;

   查询顾客的购买明细及月购买总额

select name,orderdate,cost,sum(cost) over(partition by month(orderdate)) from business;

3) 上述的场景, 将每个顾客的cost照日期进行累加

selectname,orderdate,cost,

sum(cost) over() as sample1,--所有行相加

sum(cost) over(partition by name) as sample2,--name分组,组内数据相加

sum(cost) over(partition by name order by orderdate) as sample3,--name分组,组内数据累加 - 没有指定开窗大小, 默认就是从起点到当前行, 所以和sample3一样

sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4 ,--sample3一样,由起点到当前行的聚合

sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row) as sample5, --当前行和前面一行做聚合

sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING AND 1 FOLLOWING ) as sample6,--当前行和前边一行及后面一行(相邻三行)

sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 --当前行及后面所行

from business;

sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING AND 1 PRECEDING ) as sample8,--从起点到当前行的上一行 (对于第一行到当前行上面一行找不到返回null

sum(cost) over(order by orderdate)

select id, sum(id) over(order by id) from num;

遇到两个id一样,开的窗口是一样的都是9

4) 查询每个顾客上次的购买时间

select name,orderdate,

lag(orderdate,1) over(partition by name order by orderdate)

from business; # 如果是lag是第一行为null(没有上一行), 如果是lead是最后一行为null(没有下一行)

select name,orderdate,

lag(orderdate,1,'1970-01-01') over(partition by name order by orderdate)

from business; # null的部分 默认值为1970-01-01

select name,orderdate,

lag(orderdate,1, orderdate) over(partition by name order by orderdate)

from business; # null的部分 默认值为当前行 lag是网下移

select name,orderdate,

lead(orderdate,1, orderdate) over(partition by name order by orderdate)

from business; # null的部分 默认值为当前行 lead是网上移

应用: 求单跳转化率(可以用lag函数把相邻的放在一列, 进行拼接能求出A跳转B的次数)

user_id A

user_id B  A

user_id D

user_id B

上面的变为下面的

user_id A - B

user_id B - D

user_id D - B

A->B/A

5) 查询前20%时间的订单信息 (分五组)

select * from (

select name,orderdate,cost, ntile(5) over(order by orderdate) sorted

from business

) t

where sorted = 1;

十、Rank函数

十一、其他函数

1.unix_timestamp

2. select current_stamp

十二、常用函数

1. cast(timestamp as date)  【转换成日期格式】

2. extract(year from 列名) 【提取年】

3. ifnull(check_expression , replacement_value)【if null, it is replacement_value 】

4. offset [Number of rows to skip]

5. delete a from a,b where 【删除满足某一条件table a中相应的记录】

6. Update 语句

用法1:

update table_name

set column1 = value1, column2 = value2, ...

where condition;

用法2:

update table_name set column1 = if(column1=”value1”,”value2”,”value1”)

7. sum(case when column=”value” then 数值列 else null end as) 新列名

sum聚合函数会忽略null值,将数字字段进行累加

8. datediff(date1,date2) 【计算日期间隔】

9. month(日期列) 【取月 “6”】

left(日期列,7) 【取年月 “2020-06”】

日期列 between “日期1” and “日期2” 【取时间区间】

10.  least(arg1, arg2, arg3, ...) 【返回最小值】

greatest(arg1, arg2, arg3, ...) 【返回最大值】

11. 判断奇数:emp_no % 2 = 1

12. 拼接字符串或

MySQL(concat): concat(字段1, “ ”, 字段3) as 新字段

Sqlite(||): last_name||" "||first_name as name 【中间连着空格】

13. 同一个部门的emp_no按照逗号进行连接

group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。此函数必须与 GROUP BY 配合使用。

14. 截取字符串

方法1:

substr(string,start,length)

string - 指定的要截取的字符串。

start - 必需,规定在字符串的何处开始。正数 - 在字符串的指定位置开始,负数 - 在从字符串结尾的指定位置开始,0 - 在字符串中的          第一个字符处开始。

length - 可选,指定要截取的字符串长度,缺省时返回字符表达式的值结束前的全部字符。

例如:select substr('abcdefg',3,4) from dual; 结果是cdef

select substr('abcdefg',-3,4) from dual; 结果efg

注意:字符串中的第一个位置始终为1。以下两个sql查询的结果相同:

例如:select substr('abcdefg',0,3) from dual; 结果是abc

select substr('abcdefg',1,3) from dual; 结果是abc

方法2:

left/right(字符串,位数)

15. 包含某个字段

like ‘%%’

16. 求长度函数length()

17. 替换字符串

replace(X,Y,Z)

X为要替换的字符串, Y要替换的字符串, Z用什么替换

18. Limit

LIMIT m,n : 表示从第m+1条开始,取n条数据;

LIMIT n : 表示从第0条开始,取n条数据,是limit(0,n)的缩写。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值