关于HiveQL的常用语法总结(二)——DML

本节,应该是数据库作业中使用最频繁的内容,也是至为重要的一节。但是也不必紧张,无非就是增删改查,重点在于,为什么呢?在大数据时代,最重要的两个主题是分析和挖掘。无论是分析还是挖掘,其基础都是有数据可依据,那么就需要将目标数据查找出来,因此这是最基础的一步,当然也就是用的最多的一步。

本节主要讲四个方面:导入数据,插入数据,删除数据,查询数据。

1、导入数据

一般来说,在SQL创建表后,我们可以使用insert语句插入数据。但在hive中,我们可以使用Load Data加载数据到hive表中。
插入数据到hive表中时,最好使用 LOAD DATA加载大量数据。

根据经验,应该有三种常用的导入数据情况:
1、Load data到指定的表
2、Load data到指定表的指定分区
3、 insert+select。这一种情况在插入数据章节进行讲述。

1、Load data到指定的表
直接将file,加载到指定的表,其中,表可以是普通表或者分区表。具体sql如下:

LOAD DATA LOCAL INPATH '/home/admin/test/test.txt' OVERWRITE INTO TABLE test_1  

关键字[OVERWRITE]意思是是覆盖原表里的数据,不写则不会覆盖。
关键字[LOCAL]是指你加载文件的来源为本地文件,不写则为hdfs的文件。
其中
‘home/admin/test/test.txt’是相对路径
‘/home/admin/test/test.txt’为据对路径

hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;

2、Load data到指定表的指定分区
直接将file,加载到指定表的指定分区。表本身必须是分区表,如果是普通表,导入会成功,但是数据实际不会被导入。具体sql如下:

LOAD DATA LOCAL INPATH '/home/admin/test/test.txt' OVERWRITE INTO TABLE test_1 PARTITION(pt=’xxxx)  

load数据,hive支持文件夹的方式,将文件夹内的所有文件,都load到指定表中。Hdfs会将文件系统内的某文件夹路径内的文件,分散到不同的实际物理地址中。这样,在数据量很大的时候,hive支持读取多个文件载入,而不需要限定在唯一的文件中。

hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (dt='2008-08-15');

2、插入数据

插入数据,即向一个已经存在的表中插入一些与之相匹配的数据。HQL中有两种方式:insert into 和insert overwrite。常用的方式有两种,如下图所示:
关于HiveQL的常用语法总结(二)——DML_第1张图片

假设A表和B表的字段及其数据类型都是匹配的,那么就有

--用法一
INSERT INTO TABLE A SELECT * FROM B;

--用法二
INSERT OVERWRITE TABLE A SELECT * FROM B;

如果以上A,B表数据维度或者数据类型不一样,则会报错,也有可能插入到A表中的数据是来源于多个表的,那样,就需要将多个表中的数据按照A表字段的顺序和类型进行逐个列出。

当然还有一个情况比较重要:

insert into --追加数据
insert overwrite --覆盖数据,重写数据

插入文件数据和分区数据

INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300;

3、删除数据

delect:用于删除特定行条件,你可以从给定表中删除所有的行。没用过。
TRUNCATE:truncate用于删除所有的行,这个行为在Hive元存储删除数据是不可逆的,也较少使用。* 它不能删除外部表!因为外部表里的数据并不是存放在Hive Meta store中*

truncate table IF EXISTS employees;

DROP:删除hive中的表,使用非常频繁,基本上每次创建表的时候都会用到。

DROP table IF EXISTS employees;

4、查询数据

查询数据,即找到目标数据。这一节的内容如果深究的话,可以写一本书的,因此,在此不做深究,分为基本查询、联表查询和查询优化。查询优化将放到另一片博客中去,这也是很有深度的一个问题,在那里会分享一些常见的优化策略。
首先来看看关于查询的官方语法:

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]

•使用ALLDISTINCT选项区分对重复记录的处理。默认是ALL,表示查询所有记录。DISTINCT表示去掉重复的记录
•Where 条件
•类似我们传统SQLwhere 条件
•目前支持 AND,OR ,0.9版本支持between
•IN, NOT IN
•不支持EXIST ,NOT EXIST

ORDER BY与SORT BY的不同
•ORDER BY 全局排序,只有一个Reduce任务
•SORT BY 只在本机做排序

Limit
•Limit 可以限制查询的记录数
SELECT * FROM t1 LIMIT 5

•实现Top k 查询
•下面的查询语句查询销售记录最大的 5 个销售代表。
SET mapred.reduce.tasks = 1 
SELECT * FROM test SORT BY amount DESC LIMIT 5
•REGEX Column Specification
SELECT 语句可以使用正则表达式做列选择,下面的语句查询除了 ds 和 hr 之外的所有列:
SELECT `(ds|hr)?+.+` FROM test

4.1基本查询
如上语法,举几个例子。

hive> SELECT a.foo FROM invites a WHERE a.ds='';--按条件查询
hive> INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='';--将查询数据输出到目录
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' SELECT a.* FROM pokes a;--将查询结果输出至本地目录

4.2联表查询
在hive中,关于联表查询:
•Hive 只支持等值连接(equality joins)、外连接(outer joins)和(left semi joins)。Hive 不支持所有非等值的连接,因为非等值连接非常难转化到 map/reduce 任务

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

•LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现

•join 时,每次 map/reduce 任务的逻辑是这样的:reducer 会缓存 join 序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统

•实践中,应该把最大的那个表写在最后

join 查询时,需要注意几个关键点

•只支持等值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)

•可以 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 任务

LEFT,RIGHT和FULL OUTER

例如:

SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)

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

容易混淆的问题是表分区的情况

 SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key) 
  WHERE a.ds='2010-07-07' AND b.ds='2010-07-07‘

如果 d 表中找不到对应 c 表的记录,d 表的所有列都会列出 NULL,包括 ds 列。也就是说,join 会过滤 d 表中不能找到匹配 c 表 join key 的所有记录。这样的话,LEFT OUTER 就使得查询结果与 WHERE 子句无关
解决办法是:

  SELECT c.val, d.val FROM c LEFT OUTER JOIN d 
     ON (c.key=d.key AND d.ds='2009-07-07' AND c.ds='2009-07-07')

LEFT SEMI JOIN
LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行,这样可以将where子查询改为联表查询。

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

可以被重写为:

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

UNION ALL
•用来合并多个select的查询结果,需要保证select中字段须一致
例如,

select_statement UNION ALL select_statement UNION ALL select_statement ...

你可能感兴趣的:(大数据学习)