Hadoop学习(十三)——hive的常用HQL语句

笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值,找寻数据的秘密,笔者认为,数据的价值不仅仅只体现在企业中,个人也可以体会到数据的魅力,用技术力量探索行为密码,让大数据助跑每一个人,欢迎直筒们关注我的公众号,大家一起讨论数据中的那些有趣的事情。

我的公众号为:livandata

Hadoop学习(十三)——hive的常用HQL语句_第1张图片

1 DDL操作(建表语句)

1.1、建表语法

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]

说明:

1.1) CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。

1.2) EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

LOCATOION:在建外部表时指定的数据存储目录。

create external table fz_external_table(

    id int,

    name string,

    age int,

    tel string)

ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

STORED AS TEXTFILE

LOCATION '/user/hive/external/fz_external_table';

1.3)LIKE 允许用户复制现有的表结构,但是不复制数据: 

CREATE TABLE t4 like t2; 

1.4)ROW FORMAT:创建表时指定的数据切分格式

DELIMITED [FIELDS TERMINATED BY char]

[COLLECTION ITEMS TERMINATED BY char]

[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]

|SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value,property_name=property_value, ...)]

用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的SerDe,Hive通过 SerDe 确定表的具体的列的数据。

SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化

例如:

CREATE TABLE psn (
    id int,
    name string,
    hobbies ARRAY ,
    address MAP
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '-'
MAP KEYS TERMINATED BY ':';

参考:https://www.cnblogs.com/zkio/p/7283770.html

1.5)STORED AS:

SEQUENCEFILE|TEXTFILE|RCFILE

如果文件数据是纯文本,可以使用 STORED AS TEXTFILE:默认格式,数据不做压缩,磁盘开销大,数据解析开销大。

如果数据需要压缩,使用 STORED AS SEQUENCEFILE:支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,一般建议使用BLOCK压缩。

RCFILE是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。其次,块数据列式存储,有利于数据压缩和快速的列存取。

CREATE TABLE if not exists testfile_table(

    site string,

    url  string,

    pv   bigint,

    label string)

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'

STORED AS textfile;

LOAD DATA LOCAL INPATH '/app/weibo.txt'

OVERWRITE INTO TABLE textfile_table;

1.6)CLUSTERED BY:

对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

SORTED BY:对桶中的一个或多个列另外排序。

把表(或者分区)组织成桶(Bucket)有两个理由:

1.6.1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

1.6.2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

create table stu_buck(

    sno int,

    sname string,

    sex string,

    sage int,

    sdept string)

clustered by(sno) sorted by(sno DESC) into 4 buckets

row format delimited fields terminated by ',';

1.7)COMMENT:可以为表与字段增加描述

1.8)PARTITIONED BY :根据分区来查看表中的内容,每个分区以文件夹的形式单独存在表文件夹的目录下。

2)具体实例:

2.1)创建内部表的三种方式:

2.1.1)第一种方式:

Create table if not exists default.weblog(

    Ip string,

    Time string,

    Req_url string,

    Status string,

    Size string)

Row format delimited fields terminated by ‘\t’;

数据存储:

Load data local inpath’/opt/hive/weblog.txt’ into table default.weblog;

查看数据:

Select * from default.weblog;

2.1.2)第二种方式:

Create table default.weblog

    As select ip, time, req_url, from default.weblog;

查看表结构:

Desc default.weblog;​

2.1.3)第三种方式:

Create table if not exists default.weblog_s like default.weblog;

Select * from weblog;

Desc weblog; ​

2.2)创建外部表pageview:

Create external table if not exists pageview(

    Pageid int,

    Page_url string comment ‘the page url’)

Row format delimited fields terminated by ‘,’

Location ‘hdfs://192.168.11.191:9000/user/hive/warehouse/’;

2.3)创建分区表invites:

分区是指将数据放在多个单独的文件夹中,减少运行的时间;

create table student_p(

    Sno int,

    Sname string,

    Sex string,

    Sage int,

    Sdept string)

partitioned by(part string)

row format delimited fields terminated by ','

stored as textfile;

2.3.1)内部分区表:

create table student(

    id int,

    name string) 

partitioned by (cls string) 

row format delimited fields terminated by '\t';

2.3.2)分区表装载数据:

load data local inpath '/home/airib/work/hadoop/book' into table student partition (cls='class2');
2.3.3)外部分区表:可以单独的往某个分区中导入数据;

create external table teacher (

    id int,

    name string)

partitioned by (cls string)

row format delimited fields terminated by '\t' location '/user/teacher';

location '/user/teacher'

2.4)创建带桶的表:

如何理解分桶:

Hadoop学习(十三)——hive的常用HQL语句_第2张图片

对于某一个表或者分区,hive可以进一步构建成桶,是更为细粒度的划分;一开始数据都是在一起的,建造表的时候会按照id将表分在四个文件中,分别命名为1,2,3,4;数据会对应的存入到这四个文件中,数据的存取方式为将数据按照id进行hash散列,然后按照hash散列分到四个文件中。

分桶建表的基本语法为:

Create table student(

    Id int,

    Age int,

    Name string)

Partitioned by (stat_Date string)

Clustered by (id) sorted by (age) into 2 buckets

Row format delimited fields terminated by ‘,’; ​

注意:

2.4.1)对于已有的数据,将数据导入到分桶的表中的时候是不主动分桶的,他只是记录了数据是分过桶的,文件没有变,因此在load数据的时候一般先分桶,再导入数据;

2.4.2)分桶处理时一般采用insert语句,分布进行,步骤如下:

首先:将数据load进入到一个普通的表中;

Create table t_p(id string, name string)

Row format delimited fields terminated by ‘,’;

其次:有一个分桶的开关需要打开:

set hive.enforce.bucketing = true;

set mapreduce.job.reduces = 4;

其三:然后将数据按照分桶原则从表中插入到分桶的表中,经历以下语句,数据就会被完整的分到四个桶中,四个桶分为四个不同的文件:

Insert into table t_buck

Select id, name from t_p distribute by (id) sort by (id);

reduce的数量需要与分桶的数量一致。

1.2、修改表

1)增加/删除分区

1.1)语法结构:

ALTER TABLE table_name

ADD [IF NOT EXISTS]

partition_spec [ LOCATION'location1' ]

partition_spec [ LOCATION 'location2' ] ...

其中partition_spec为:

PARTITION (partition_col = partition_col_value, partition_col =partiton_col_value, ...)

ALTER TABLE table_name DROP partition_spec, partition_spec,...

1.1.1)增加分区:

alter table student_p add partition(part='a') partition(part='b');

1.1.2)删除分区:

show partitions student;

alter table student_p drop partition(stat_date='20160105');

alter table student_p add partition(stat_date=’20140101’)

location ‘/user/hive/warehouse/student’ partition(stat_Date=’ 20140102’)

1.1.3)重命名表:

语法结构:

ALTER TABLE table_name RENAME TO new_table_name

具体实例:

alter table students renameto students1;

show tables; ​

2)增加/更新列:

2.1)语法结构:

ALTER TABLE table_name

ADD|REPLACE COLUMNS (

col_name data_type[COMMENT col_comment], ...

)

与:

 ALTER TABLE table_name

CHANGE [COLUMN] col_old_name col_new_namecolumn_type

[COMMENT col_comment]

[FIRST|AFTER column_name]

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

2.1.1)增加列:

Alter table students add columns(name1 string);

2.1.2)更新列:

Alter table students replace columns(id int, age int, name string);

Hadoop学习(十三)——hive的常用HQL语句_第3张图片

3)删除列:

alter table students drop columns id;

4)修改列:

alter table students change columns salary salary double;

5)删除表:

drop table if exists employee;

6)修改桶:

alter table btest3 clustered by(name, age) sorted by(age) into10 buckets;

显示命令:

show tables

show databases

show partitions

show functions

desc extended t_name;

desc formatted table_name;

2 DML操作(数据操纵语句)

2.1、Load(复制/移动操作):

1)语法结构:

LOAD DATA [LOCAL] INPATH 'file path' [OVERWRITE] INTO

TABLE tablename

[PARTITION (partcol1=val1, partcol2=val2 ...)]

说明:

1.1)Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。

1.2)file path移动路径:

相对路径,例如:project/data1

绝对路径,例如:/user/hive/project/data1

包含模式的完整 URI,列如:hdfs://namenode:9000/user/hive/project/data1

1.3)LOCAL关键字:

如果没有指定 LOCAL 关键字,则根据inpath中的uri查找文件

如果指定了LOCAL,那么:

load 命令会去查找本地文件系统中的file path。如果发现是相对路径,则路径会被解释为相对于当前用户的当前路径。

load 命令会将file path中的文件复制到目标文件系统中。目标文件系统由表的位置属性决定。被复制的数据文件移动到表的数据对应的位置。

如果没有指定 LOCAL关键字,如果file path指向的是一个完整的URI,hive 会直接使用这个URI。否则:如果没有指定schema或者authority,Hive 会使用在hadoop配置文件中定义的schema和authority,fs.default.name指定了 Namenode的URI。

如果路径不是绝对的,Hive相对于/user/进行解释。

Hive 会将filepath中指定的文件内容移动到table(或者partition)所指定的路径中。    

1.4)OVERWRITE关键字

如果使用了OVERWRITE关键字,则目标表(或者分区)中的内容会被删除,然后再将file path指向的文件/目录中的内容添加到表/分区中。

如果目标表(分区)已经有一个文件,并且文件名和file path中的文件名冲突,那么现有的文件会被新文件所替代。

1.4.1)加载相对路径数据:

Load data local inpath ‘buckets.txt’ into table student partition(stat_Date=’20130202’);

Dfs -ls /user/hive/warehouse/student/stat_date=20130202​

1.4.2)加载绝对路径数据:

Load data local inpath ‘/root/app/datafile/buckets.txt’ into table student partition(stat_Date=’20130202’);

Dfs -ls /user/hive/warehouse/student/stat_date=20130202​;

1.4.3)加载包含模式的完整url:

Load data local inpath ‘http://192.168.22.22:9000/root/app/datafile/buckets.txt’ into table student partition(stat_Date=’20130202’);

Dfs -ls /user/hive/warehouse/student/stat_date=20130202​;

1.4.4)OVERWRITE关键字使用:

Load data local inpath ‘buckets.txt’ overwrite into table student partition(stat_Date=’20130202’);

Dfs -ls /user/hive/warehouse/student/stat_date=20130202​;

2.2、Insert(插入语句):将查询结果插入Hive表

1)语法结构:

1.1)Base insert:

INSERT OVERWRITE TABLE tablename1

[PARTITION (partcol1=val1, partcol2=val2 ...)]

SELECT select_statement1

FROM from_statement

1.2)Multiple inserts:

FROM from_statement

INSERT OVERWRITE TABLE tablename1

[PARTITION (partcol1=val1, partcol2=val2 ...)]

SELECT select_statement1

[INSERT OVERWRITE TABLE tablename2

[PARTITION ...]

SELECT select_statement2] ...

1.3)Dynamic partition inserts:

INSERT OVERWRITE TABLE tablename

PARTITION (partcol1[=val1], partcol2[=val2] ...)

SELECT select_statement

FROM from_statement

2)具体案例:

2.1)追加数据:insert into是指后面追加内容,原有的内容不删除;

insert into table account1 select * from account_tmp;

2.2)覆盖数据:覆盖原有的内容;

insert overwrite table account1 select * from account_tmp;

2.3)多插入模式:

From student

Insert overwrite table student partition(stat_date=’20140202’)

Select id, age, name, where stat_date=’20130202’

Insert overwrite table student partition(stat_date=’20140203’)

Select id, age, name, where stat_date=’20130203’

2.4)动态分区模式:

Insert overwrite table student1 partition(stat_date)

Select id, age, name, stat_date from student where stat_date=’20140203’

3) 导出表数据:

3.1)Base insert:

INSERT OVERWRITE [LOCAL] DIRECTORY directory1

SELECT ... FROM ...

3.1)multiple inserts:

FROM from_statement

INSERT OVERWRITE [LOCAL] DIRECTORY directory1

SELECT select_statement1

[INSERT OVERWRITE [LOCAL] DIRECTORY directory2

SELECT select_statement2]...

4)具体实例:

4.1)导出文件到本地:

Insert overwrite local directory ‘/root/app/datafile/student1’

Select * from student1

说明:数据写入到文件系统时进行文本序列化,且每列用^A来区分,\n为换行符。用more命令查看时不容易看出分割符,可以使用: sed -e 's/\x01/|/g' filename来查看。

4.2)导出数据到HDFS:

Insert overwrite directory ‘hdfs://192.168.122.11:9000/user/hive/warehouse/mystudent’

Select * from student1;

Dfs -ls /user/hive/warehouse/mystudent;

注意:

insert...select:一般是表对表。

往表中导入数据时,查询的字段个数必须和目标的字段个数相同,不能多,也不能少,否则会报错。但是如果字段的类型不一致的话,则会使用null值填充,不会报错。

load data:一般是将外部文件放到hive中。

形式往hive表中装载数据时,则不会检查。如果字段多了则会丢弃,少了则会null值填充。同样如果字段类型不一致,也是使用null值填充。

2.3、SELECT:

1)语法结构:

SELECT [ALL | DISTINCT]

select_expr, select_expr, ...

FROM table_reference

[WHERE where_condition]

[GROUP BY col_list [HAVING condition]]

[CLUSTER BY col_list|[DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]]

[LIMIT number]

注:

1.1)order by:会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。

1.2)sort by:不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。

1.3)distribute by(字段):根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。

1.4)cluster by(字段):除了具有Distribute by的功能外,还会对该字段进行排序。

如果分桶和sort字段是同一个时,此时:cluster by = distribute by + sort by

分桶表的作用:最大的作用是用来提高join操作的效率;

(思考这个问题:select a.id, a.name, b.addr from a join b on a.id = b.id;

如果a表和b表已经是分桶表,而且分桶的字段是id字段

做这个join操作时,还需要全表做笛卡尔积吗?)

保存select查询结果的几种方式:

1.5)将查询结果保存到一张新的hive表中:

Create table t_tmp

As

Select * from t_p;

1.6)将查询结果保存到一张已经存在的hive表中:

Insert into table t_tmp

Select * from t_p;

1.7)将查询结果保存到指定的文件目录中(可以是本地,也可以是hdfs):

Insert into local directory ‘/home/Hadoop/test’

Select * from t_p;

2) 具体实例:

2.1)获取年龄大的3个学生:

Select id, age, name

from student

where stat_date=’20140203’

order by age desc

limit 3;

2.2)查询学生信息按年龄,降序排序:

Order by:全局排序,生成一个reducer;

Sort by:分区内排序,可生成多个reducer;

Eg:

Set mapred.reduce.tasks=4;

Select * from student sort by age desc;

2.3)按学生名称汇总学生年龄:

Select name, sum(age) from student group by name;

2.4)分区划分查询:

Distribute by:按照指定的字段或表达式对数据进行划分,输出到对应的reduce或者文件中;

cluster by:区内排序,如果distribute by,sort by使用的两个字段相同时:cluster by=distribute by+sort by功能叠加;

set mapred.reduce.tasks=2;

insert overwrite local directory 'tmp/lxw1234/'

select id from lxw1234_com

distribute by id;

上面会生成两个文件;

set mapred.reduce.tasks=2;

insert overwrite local directory 'tmp/lxw1234/' 

select id from lxw1234_com

cluster by id;

上面会排序;

2.5)子查询:必须设置别名

select * from (select a+b as col form t1) t2;

2.6)where中的子查询:

left semi join语句用来替代exists/in子句:

在hive中下面的语句是无法使用的:

select * from A where A.a in (select foo from B);

select * from A where A.a exists (select foo from B where A.x=B.x);

需要使用left semi join子句:

select * from A left semi join B on(A.key=B.key);

2.7)将子查询作为一个表:hive可以通过with查询来提高查询性能,因为先通过with语法将数据查询到内存,然后后面其它查询可以直接使用。

with q1 as (select * from A where x>65)

from q1

insert overwrite table q2

select *;

2.8)虚拟列:

input_file_name:数据对应的HDFS文件;

block_offset_inside_file:该行记录在文件中的偏移量;

select id, input_file_name, block_offset_inside_file from lxm1234_com;

2.4、Hive Join:

1)语法结构:

join_table:

table_reference JOIN table_factor [join_condition]

  | table_reference {LEFT|RIGHT|FULL}  [OUTER]  JOIN table_reference join_condition

  | table_reference LEFT SEMIJOIN table_reference  join_condition

Hive支持等值连接(equalityjoins)\外连接(outer joins)和左右连接(left/rightjoins)。

Hive不支持非等值的连接,因为非等值连接非常难转化到 map/reduce 任务。

另外,Hive支持多于2个表的连接,缓存前面的表,拿最后一个表逐行进行join。

2)join注意几个关键点:

2.1)只支持等值join:

例如:

SELECT a.* FROM a JOIN b ON (a.id = b.id)

SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department =b.department)

是正确的,然而:

SELECT a.* FROM a JOIN b ON (a.id>b.id)

是错误的。

2.2)可以 join 多于2个表:

例如:

SELECT a.val,b.val, c.val

FROM a JOIN b

ON (a.key =b.key1) JOIN c ON (c.key = b.key2)

如果join中多个表的join key是同一个,则join会被转化为单个map/reduce 任务,例如:

SELECT a.val,b.val, c.val

FROM a JOIN b

ON (a.key =b.key1) JOIN c ON (c.key =b.key1)

被转化为单个map/reduce任务,因为join中只使用了b.key1作为join key。

SELECT a.val, b.val, c.val

FROM a JOIN b

ON (a.key =b.key1) JOIN c ON(c.key = b.key2)

而这一join 被转化为2个map/reduce任务。因为b.key1用于第一次join 条件,而b.key2用于第二次join。

2.3)join 时,每次 map/reduce 任务的逻辑如下:

reducer会缓存join序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统。这一实现有助于在reduce端减少内存的使用量。实践中,应该把最大的那个表写在最后(否则会因为缓存浪费大量内存)。

例如:

SELECT a.val, b.val, c.val

FROM a JOIN b

ON(a.key = b.key1) JOIN c ON (c.key = b.key1)

所有表都使用同一个join key(使用 1 次 map/reduce 任务计算)。Reduce 端会缓存a表和b表的记录,然后每次取得一个c表的记录就计算一次join 结果,类似的还有:

SELECT a.val,b.val, c.val

FROM a JOIN b

ON(a.key = b.key1) JOIN c ON (c.key = b.key2)

这里用了2次map/reduce任务。第一次缓存a表,用b表序列化;第二次缓存第一次 map/reduce 任务的结果,然后用c表序列化。

2.4)LEFT,RIGHT和FULL OUTER关键字用于处理join中空记录的情况:

例如:

SELECT a.val, b.val

FROM a LEFT OUTER JOIN b

ON (a.key=b.key)

对应所有a表中的记录都有一条记录输出。输出的结果应该是a.val,b.val,当 a.key=b.key时,而当b.key中找不到等值的a.key记录时也会输出:

a.val, NULL

所以 a 表中的所有记录都被保留了;

SELECT A.val, B.val

FROM A RIGHT OUTER JOIN B

ON(A.key=B.key);

会保留所有b表的记录。

2.5)Join 发生在 WHERE 子句之前:

如果你想限制join的输出,应该在WHERE子句中写过滤条件——或是在join 子句中写。这里面一个容易混淆的问题是表分区的情况:

SELECT a.val,b.val

FROM a LEFT OUTER JOIN b

ON (a.key=b.key)

WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

上例会join a表到b表(OUTER JOIN),列出a.val和b.val的记录。WHERE 从句中可以使用其他列作为过滤条件。但是,如前所述,如果 b 表中找不到对应 a 表的记录,b 表的所有列都会列出 NULL,包括 ds 列。也就是说,join 会过滤 b 表中不能找到匹配a表join key的所有记录。这样的话,LEFT OUTER就使得查询结果与WHERE子句无关了。解决的办法是在OUTER JOIN时使用以下语法:

SELECT a.val, b.val

FROM a LEFT OUTER JOIN b

ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')

这一查询的结果是预先在join阶段过滤过的,所以不会存在上述问题。这一逻辑也可以应用于RIGHT和FULL类型的join中。

2.6)Join 是不能交换位置的:

无论是LEFT还是RIGHT join,都是左连接的。

SELECT a.val1,a.val2, b.val, c.val

FROM a JOIN b ON(a.key = b.key)

LEFT OUTER JOIN c ON (a.key = c.key)

先join a表到b表,丢弃掉所有join key中不匹配的记录,然后用这一中间结果和c表做join。这一表述有一个不太明显的问题,就是当一个key在a表和c表都存在,但是b表中不存在的时候:整个记录在第一次join,即a JOIN b的时候都被丢掉了(包括a.val1,a.val2和a.key),然后我们再和c 表 join的时候,如果c.key与a.key或b.key相等,就会得到这样的结果:NULL, NULL, NULL, c.val

2.7)内连接inner join,只返回满足条件的结果:

SELECT t.dept, e.name

FROM employees e INNER JOIN dept t

ON e.deptno=t.deptno;

2.8)查询带桶的内容:

SELECT *

FROM bucketed_user

TABLESAMPLE(bucket 1 out of 2 on id)

WHERE day='20180703';

语法:

tablesample(bucket x out of y):桶抽样

y必须是table总bucket数的因子或者倍数。hive根据y的大小决定抽样的比例。

例如:table共有64份,当y=32时,抽取(64/32)个bucket,即两个,当y=128时,抽取(64/128)=1/2个桶的数据;

x表示从哪个桶开始抽数据。

例如:table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16)=2个bucket的数据,分别为第3个bucket和第3+16=19个bucket的数据;

2.5、update:

1)hive中的update语句会有一定的限制:

1.1)必须带有分桶属性(buckets);

1.2)需要指定orc file format和acid output format格式;

1.3)建表时必须指定参数(‘transactional’=true);

1.4)必须首先修改hive-site.xml中的内容;

2)其次:

Create table student(

id int,

name string)

clustered by(name) into 2 buckets 

stored as orc tblproperties('transactional'='true');

3)其三:

update student set id='444' 

where name='tom';

2.6、delete:

1)删除表:

Drop table if exists students;

2)删除表中所有内容:

Truncate table employees;

3)删除表中部分数据:

Insert overwrite table table1 select * from table1 where XXXX;

XXXX是表中需要保留的数据;

4)具体实例:

4.1)获取已经分配班级的学生姓名:

SELECT name, classname

FROM student a join class b ON(a.name=b.std_name);

4.2)获取尚未分配班级的学生姓名:

SELECT name, classname

FROM student a left join class b ON (a.name=b.std_name)

WHERE b.std_name is null;

4.3)LEFT SEMI JOIN是IN/EXISTS的高效实现:

SELECT id, name

FROM student a LEFT SEMI JOIN class b ON (a.name=b.std_name);

3 Hive的sql案例:

3.1、查询全体学生的学号与姓名:

hive>select Sno,Sname from student;

3.2、查询选修了课程的学生姓名:

hive>select distinct Sname from student inner join sc on student.Sno=Sc.Sno;

----hive的group by 和集合函数

3.3、查询学生的总人数:

hive>select count(distinct Sno)count from student;

3.4、计算1号课程的学生平均成绩

hive>select avg(distinct Grade) from sc where Cno=1;

3.5、查询各科成绩平均分

hive> select Cno,avg(Grade) from sc group by Cno; 

3.6、查询选修1号课程的学生最高分数:

select Grade from sc where Cno=1 sort by Grade desc limit 1;

(注意比较:select * from sc where Cno=1 sort by Grade

             select Grade from sc where Cno=1 order by Grade)    

3.7、求各个课程号及相应的选课人数:

hive>select Cno,count(1) from sc group by Cno;

3.8、查询选修了3门以上的课程的学生学号

hive>select Sno from (select Sno,count(Cno) CountCno from sc group by Sno)a wherea.CountCno>3;

或:

hive>select Sno from sc group by Sno having count(Cno)>3;

----hive的Order By/Sort By/Distribute By

Order By:在strict 模式下(hive.mapred.mode=strict),orderby 语句必须跟着limit语句,但是在nonstrict下就不是必须的,这样做的理由是必须有一个reduce对最终的结果进行排序,如果最后输出的行数过多,一个reduce需要花费很长的时间。

3.9、查询学生信息,结果按学号全局有序:

hive>set hive.mapred.mode=strict;   <默认nonstrict>

hive> select Sno from student order by Sno;

FAILED: Error in semantic analysis: 1:33 In strict mode, if ORDER BYis specified, LIMIT must also be specified. Error encountered near token 'Sno'

Sort By:它通常发生在每一个redcue里,“order by” 和“sort by"的区别在于,前者能给保证输出都是有顺序的,而后者如果有多个reduce的时候只是保证了输出的部分有序。set mapred.reduce.tasks=在sort by可以指定,在用sort by的时候,如果没有指定列,它会随机的分配到不同的reduce里去。distribute by 按照指定的字段对数据进行划分到不同的输出reduce中

此方法会根据性别划分到不同的reduce中,然后按年龄排序并输出到不同的文件中。

3.10、查询学生信息,按性别分区,在分区内按年龄有序

hive>set mapred.reduce.tasks=2;

hive>insert overwrite local directory '/home/hadoop/out'

select * from student distribute by Sex sort by Sage;

----Join查询,join只支持等值连接

3.11、查询每个学生及其选修课程的情况

hive>select student.*,sc.* from student join sc on (student.Sno =sc.Sno);

3.12、查询学生的得分情况。

hive>selectstudent.Sname,course.Cname,sc.Grade from student join sc on student.Sno=sc.Snojoin course on sc.cno=course.cno;

3.13、查询选修2号课程且成绩在90分以上的所有学生。

hive>select student.Sname,sc.Grade from student join sc on student.Sno=sc.Sno 

where sc.Cno=2 and sc.Grade>90;

----LEFT,RIGHT 和 FULL OUTER JOIN ,inner join, left semi join

3.14、查询所有学生的信息,如果在成绩表中有成绩,则输出成绩表中的课程号

hive>select student.Sname,sc.Cno from student left outer join sc onstudent.Sno=sc.Sno;

如果student的sno值对应的sc在中没有值,则会输出student.Snamenull.如果用right out join会保留右边的值,左边的为null。

Join 发生在WHERE 子句之前。如果你想限制join 的输出,应该在 WHERE 子句中写过滤条件——或是在join 子句中写。

----LEFT SEMI JOIN:Hive 当前没有实现IN/EXISTS 子查询,可以用 LEFT SEMI JOIN 重写子查询语句

重写以下子查询为LEFT SEMI JOIN:

SELECT a.key, a.value FROM a WHERE a.key exist in (SELECTb.key FROM B);

可以被重写为:

SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key)

3.15、查询与“刘晨”在同一个系学习的学生:

hive>select s1.Sname from student s1 left semi join student s2 on s1.Sdept=s2.Sdeptand s2.Sname='刘晨';

注意比较:

select *

from student s1 left join student s2 on s1.Sdept=s2.Sdept and s2.Sname='刘晨';

select *

from student s1 right join student s2 on s1.Sdept=s2.Sdept and s2.Sname='刘晨';

select *

from student s1 inner join student s2 on s1.Sdept=s2.Sdept and s2.Sname='刘晨';

select *

from student s1 left semi join student s2 ons1.Sdept=s2.Sdept and s2.Sname='刘晨';

select s1.Sname

from student s1 right semi join student s2 ons1.Sdept=s2.Sdept and s2.Sname='刘晨';

以上为常用的HQL的基本语法,如有补充后续会继续跟进。

你可能感兴趣的:(hadoop,HIVE)