11.3.3 SQL操作

下面是一个标准的Select语句语法定义:


SELECT[ALL|DISTINCT]select_expr, select_expr,……

FROM table_reference

[WHERE where_condition]

[GROUP BY col_list]

[CLUSTER BY col_list

|[DISTRIBUTE BY col_list][SORT BY col_list]

]

[LIMIT number]


下面对其中重要的定义进行说明。

(1)table_reference

table_reference指明查询的输入,它可以是一个表、一个视图或一个子查询。下面是一个简单的查询,检索所有表t1中的列和行:


SELECT*FROM t1


(2)WHERE

where_condition是一个布尔表达式。比如下面的查询只输出sales表中amount>10且region属性值为US的记录:


SELECT*FROM sales WHERE amount>10 AND region="US"


(3)ALL和DISTINCT

ALL和DISTINCT选项可以定义重复的行是否要返回。如果没有定义,那么默认为ALL,即输出所有的匹配记录而不删除重复的记录,代码如下:


hive>SELECT col1,col2 FROM t1

1 3

1 3

1 4

2 5

hive>SELECT DISTINCT col1,col2 FROM t1

1 3

1 4

2 5

hive>SELECT DISTINCT col1 FROM t1

1

2


(4)LIMIT

LIMIT可以控制输出的记录数,随机选取检索结果中的相应数目输出:


SELECT*FROM t1 LIMIT 5


下面代码为输出Top-k, k=5的查询结果:


SET mapred.reduce.tasks=1

SELECT*FROM sales SORT BY amount DESC LIMIT 5


(5)使用正则表达式

SELECT声明可以匹配使用一个正则表达式的列。下面的例子会对sales表中除了ds和hr的所有列进行扫描:


SELECT(ds|hr)?+.+FROM sales


(6)基于分区的查询

通常来说,SELECT查询要扫描全部的表。如果一个表是使用PARTITIONED BY语句产生的,那么查询可以对输入进行“剪枝”,只对表的相关部分进行扫描。Hive现在只对在WHERE中指定的分区断言进行“剪枝”式的扫描。举例来说,如果一个表page_view按照date列的值进行了分区,那么下面的查询可以检索出日期为2010-03-01的行记录:


SELECT page_views.*

FROM page_views

WHERE page_views.date>='2010-03-01'AND page_views.date<='2010-03-31'


(7)HAVING

Hive目前不支持HAVING语义,但是可以使用子查询实现,示例如下:


SELECT col1 FROM t1 GROUP BY col1 HAVING SUM(col2)>10


可以表示为:


SELECT col1 FROM(SELECT col1,SUM(col2)AS col2sum FROM t1 GROUP BY col1)t2

WHERE t2.col2sum>10


我们可以将查询的结果写入到目录中:


hive>INSERT OVERWRITE DIRECTORY'/tmp/hdfs_out'SELECT a.*FROM invites a WHERE

a.ds='2009-09-01';


上面的例子将查询结果写入/tmp/hdfs_out目录中。也可以将查询结果写入本地文件路径,如下所示:


hive>INSERT OVERWRITE LOCAL DIRECTORY'/tmp/local_out'SELECT a.*FROM pokes a;


其他(例如GROUP BY和JOIN)的作用和SQL相同,就不再赘述,下面是使用的例子,详细信息可以查看http://wiki.apache.org/hadoop/Hive/LanguageManual。

(8)GROUP BY


hive>FROM invites a INSERT OVERWRITE TABLE events SELECT a.bar, count(*)WHERE

a.foo>0 GROUP BY a.bar;

hive>INSERT OVERWRITE TABLE events SELECT a.bar, count(*)FROM invites a WHERE

a.foo>0 GROUP BY a.bar;


(9)JOIN


hive>FROM pokes t1 JOIN invites t2 ON(t1.bar=t2.bar)INSERT OVERWRITE TABLE

events SELECT t1.bar, t1.foo, t2.foo;


(10)多表INSERT


FROM src

INSERT OVERWRITE TABLE dest1 SELECT src.*WHERE src.key<100

INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key>=100 and

src.key<200

INSERT OVERWRITE TABLE dest3 PARTITION(ds='2010-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;


(11)STREAMING


hive>FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar)

AS(oof, rab)USING'/bin/cat'WHERE a.ds>'2010-08-09';


这个命令会将数据输入给Map操作(通过/bin/cat命令),同样也可以将数据流式输入给Reduce操作。