前の章では、それぞれHiveのデータ定義とデータ操作について説明しました。この章では、主にHiveクエリについて説明します。「繭を壊して蝶になる-ビッグデータ」のコラムに注目して、関連するコンテンツをもっと見てください〜
目次
1.基本的なクエリ
まず、クエリステートメントの構文は次のように要約できます。
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]
まず、基本的なクエリ操作、つまりフィルター条件を含まないクエリを見てみましょう。例から始めましょう。前に作成したpeopleテーブルを例として取り上げます。このテーブルには、id、name、genderの3つの列が含まれています。読者の便宜のために、作成プロセスをここに掲載します。もちろん、紹介された以前のブログも読むことができます。
1.最初にpeopleテーブルを作成します。
create table if not exists people(
id string,
name string,
sex string
)
row format delimited fields terminated by ',';
2.テストデータを作成します。
3.データをpeopleテーブルにロードします。
load data local inpath '/root/files/p.txt' into table people;
1.1完全なテーブルクエリ
1.1.1完全なテーブルクエリ
1.1.2指定された列をクエリする
1.2エイリアス
クエリ列にエイリアスを付けることで、元の列の名前を変更できます。
1.3算術演算子
算術演算子を使用して、クエリの内容に対して基本的な操作を実行できます。一般的な算術演算子は次のとおりです。
オペレーター |
説明 |
A + B |
AとBを追加 |
AB |
マイナスB |
A * B |
AとBを掛ける |
A / B |
AをBで割ったもの |
A%B |
AからBが残りを取ります |
A&B |
AとBのビットごとのAND |
A | B |
AとBのビットごとのOR |
A ^ B |
AとBのビット単位のXOR |
〜A |
Aはビットで反転されます |
1.4一般的に使用される基本機能
関数を使用すると、クエリのコンテンツに対して対応する操作を実行できます。一般的に使用される基本的な関数の一部を次に示します。
関数 |
説明 |
カウント() |
レコードの数を見つける |
max() |
最大値を見つける |
最小() |
最小値を見つける |
avg() |
平均 |
和() |
和 |
次に、LIMITステートメント
LIMITステートメントを使用して、クエリの数を制限できます。
3、WHEREステートメント
WHEREステートメントを使用して、次の条件を満たさないデータをフィルタリングします。
3.1比較演算子
一般的に使用される比較演算子は次のとおりです。
オペレーター |
サポートされているデータ型 |
説明 |
A = B |
基本データ型 |
AがBと等しい場合はTRUEを返し、そうでない場合はFALSEを返します。 |
A <=> B |
基本データ型 |
AとBの両方がNULLの場合、TRUEを返し、もう一方は等号(=)演算子の結果と同じです。どちらかがNULLの場合、結果はNULLです。 |
A <> B、A!= B |
基本データ型 |
AまたはBがNULLの場合はNULLを返し、AがBと等しくない場合はTRUEを返し、そうでない場合はFALSEを返します。 |
A <B |
基本データ型 |
AまたはBがNULLの場合はNULLを返し、AがBより小さい場合はTRUEを返し、それ以外の場合はFALSEを返します。 |
A <= B |
基本データ型 |
AまたはBがNULLの場合はNULLを返し、AがB以下の場合はTRUEを返し、それ以外の場合はFALSEを返します。 |
A> B |
基本データ型 |
AまたはBがNULLの場合はNULLを返し、AがBより大きい場合はTRUEを返し、それ以外の場合はFALSEを返します。 |
A> = B |
基本データ型 |
AまたはBがNULLの場合はNULLを返し、AがB以上の場合はTRUEを返し、それ以外の場合はFALSEを返します。 |
A [NOT] BとCの間 |
基本データ型 |
A、B、またはCのいずれかがNULLの場合、結果はNULLになります。Aの値がB以上でC以下の場合、結果はTRUEになり、それ以外の場合はFALSEになります。NOTキーワードを使用すると、逆の効果が得られます。 |
AはNULLです |
すべてのデータ型 |
AがNULLに等しい場合はTRUEを返し、そうでない場合はFALSEを返します。 |
AはNULLではありません |
すべてのデータ型 |
AがNULLに等しくない場合はTRUEを返し、そうでない場合はFALSEを返します。 |
IN(数値1、値2) |
すべてのデータ型 |
IN操作を使用して、リストに値を表示します |
A [NOT] LIKE B |
STRINGタイプ |
BはSQLの単純な正規表現であり、ワイルドカードパターンとも呼ばれます。Aがそれに一致する場合はTRUEを返し、そうでない場合はFALSEを返します。Bの表現は次のように説明されます。「x%」はAが文字「x」で始まる必要があることを意味し、「%x」はAが文字「x」で終わる必要があることを意味し、「%x%」はAが文字を含むことを意味します'x'、文字列の最初、最後、または途中にすることができます。NOTキーワードを使用すると、逆の効果が得られます。 |
RLIKE B、A REGEXP B |
STRINGタイプ |
B是基于java的正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
3.2 逻辑运算符
WHERE语句中常用的逻辑运算符如下所示:
操作符 |
描述 |
AND |
并 |
OR |
或 |
NOT |
否 |
四、分组函数
4.1 GROUP BY语句
GROUP BY语句通常会跟聚合函数一起使用,下面的例子统计了people表中所有不同性别的总人数:
select sex,count(*) from people group by sex;
4.2 HANING子句
HAVING子句只能用于GROUP BY子句之后,且与WHERE不同的是,HAVING后面可以使用分组函数。
select sex,count(*) sl from people group by sex having sex = 'm';
五、JOIN语句
JOIN语句代表多表关联,这里需要注意的是它只支持等值连接,不支持非等值连接。那我们再建一张favorite表的,表示用户的兴趣爱好。favorite表有三个字段,分别是id、姓名和兴趣。
create table if not exists favorite(
id string,
name string,
fav string
)
row format delimited fields terminated by ',';
下面是一个JOIN的例子:
select p.name,p.sex,f.fav from people p join favorite f on p.name = f.name;
上例就是一个内连接的例子,内连接是指只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。左外连接(LEFT JOIN)是指JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。右外连接(RIGHT JOIN)是指JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。满外连接(FULL JOIN)将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。Hive会对每对JOIN连接对象启动一个MapReduce任务。
六、排序
6.1 Order by语句
使用Order by进行全局排序,它只有一个Reducer。默认是升序排序,即ASC(ascend)。也可以使用DESC(descend)指定为降序排列。
select * from people order by sex desc;
可以指定多个列排序:
select * from people order by sex,id desc;
6.2 Sort by语句
对于大规模的数据集来说order by的效率非常低。在很多情况下,并不需要全局排序,此时可以使用sort by进行排序。Sort by为每个reducer产生一个排序文件,每个Reducer内部进行排序,对全局结果集来说并不是有序的。下面来看一个例子:将people表中的数据根据id降序排序输出到文件中。
因为使用Sort by可能会有多个Reducer,可以使用如下语句在命令行指定Reducer的个数,此命令只对当前命令行有效。
set mapreduce.job.reduces=3 # 设置Reducer的个数为3
insert overwrite local directory '/root/files/people.txt' select * from people sort by id desc;
6.3 Distribute By语句
在有些情况下,我们需要控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。分区排序(Distribute By)可以用来处理这种情况。分区排序类似MapReduce中的自定义分区,它结合sort by使用。对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。distribute by的分区规则是根据分区字段的hash码与reduce的个数进行模除后,余数相同的分到一个区。来看个例子:先按照性别分区,然后按照id降序输出。
set mapreduce.job.reduces=3;
select * from people distribute by sex sort by id desc;
6.4 Cluster By语句
当distribute by和sorts by字段相同时,可以使用cluster by方式。cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。例如,以下两种写法是等价的:
select * from people cluster by sex;
select * from people distribute by sex sort by sex;
七、分桶查询
分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。对于一张表或者分区,Hive可以进一步组织成桶,也就是更为细粒度的数据范围划分。分桶是将数据集分解成更容易管理的若干部分的另一个技术。分区针对的是数据的存储路径;分桶针对的是数据文件。下面来看一个分桶表的例子。
1、首先来构造测试数据,数据分为两列,一列是id,一列是name。如下所示:
2、创建分桶表,这里需要注意的是,在创建分桶表之前,需要设置强制分桶属性。属性设置如下:
set hive.enforce.bucketing=true;
在建表之前需要注意的是,因为分桶表加载数据必须得走MapReduce,所以使用load的方式加载数据是不会进行分桶的,故得需要使用insert的方式加载其他表中的数据。建表语句如下:
1、普通表
create table stu(id int, name string) row format delimited fields terminated by ',';
2、分桶表
create table students(id int, name string) clustered by(id) into 4 buckets row format delimited fields terminated by ',';
3、加载数据
1、使用load的方式将构造的数据加载到stu普通表中
load data local inpath '/root/files/stu.txt' into table stu;
2、使用insert方式将stu中的数据加载到students中
insert into table students select id, name from stu;
4、加载数据完成后查看监控界面,发现已经将数据分成了四个桶。
对于大数据量的数据集,有时候我们需要对其进行抽样查询,此时可以使用桶表来完成这个需求操作。其语法如下:
TABLESAMPLE(BUCKET x OUT OF y)
其中,y必须是table总bucket数的倍数或者因子。Hive根据y的大小,决定抽样的比例。x表示从哪个bucket开始抽取,如果需要取多个分区,以后的分区号为当前分区号加上y。例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第3(x+y)个bucket的数据。这里必须注意的是x的值必须小于等于y的值。例如:
select * from students tablesample(bucket 1 out of 4 on id);
本文到这就接近尾声了,你们在此过程中遇到了什么问题,欢迎留言,让我看看你们都遇到了哪些问题~