1. 程式人生 > >[一起學Hive]之九-Hive的查詢語句SELECT

[一起學Hive]之九-Hive的查詢語句SELECT

八、Hive的查詢語句SELECT

在所有的資料庫系統中,SELECT語句是使用最多,也最複雜的一塊,Hive中的查詢語句SELECT支援的語法當然也比較複雜,本文只能盡力去介紹。

8.1 基礎查詢語法

Hive中的SELECT基礎語法和標準SQL語法基本一致,支援WHERE、DISTINCT、GROUP BY、ORDER BY、HAVING、LIMIT、子查詢等;
語法如下:

  1. [WITH CommonTableExpression(,CommonTableExpression)*]
  2. SELECT [ALL | DISTINCT] select_expr, select_expr,...
  3. FROM table_reference
  4. [WHERE where_condition]
  5. [GROUP BY col_list]
  6. [CLUSTER BY col_list
  7. |[DISTRIBUTE BY col_list][SORT BY col_list]
  8. ]
  9. [LIMIT number]

下面介紹Hive中比較特殊的一些查詢語法。

8.2 ORDER BY和SORT BY

ORDER BY用於全域性排序,就是對指定的所有排序鍵進行全域性排序,使用ORDER BY的查詢語句,最後會用一個Reduce Task來完成全域性排序。
SORT BY用於分割槽內排序,即每個Reduce任務內排序。
看下面的例子:
原表資料為:

  1. hive>select*from lxw1234_com;
  2. OK
  3. 5
  4. 3
  5. 6
  6. 2
  7. 9
  8. 8
  9. 1

使用ORDER BY

  1. hive>select*from lxw1234_com order by id;
  2. 1
  3. 2
  4. 3
  5. 5
  6. 6
  7. 8
  8. 9

使用SORT BY

hive> set mapred.reduce.tasks=2;
hive> select * from lxw1234_com sort by id;
2
5
6
9
1
3
8

設定了2個reduce,從結果可以看出,每個reduce內做了排序。
如果reduce數為1,那麼ORDER BY和SORT BY的結果是一樣的:

  1. hive>set mapred
    .reduce.tasks=1;
  2. hive>select*from lxw1234_com sort by id;
  3. 1
  4. 2
  5. 3
  6. 5
  7. 6
  8. 8
  9. 9

真實業務環境中,我們的需求大多需要使用ORDER BY全域性排序來完成。

8.3 DISTRIBUTE BY和CLUSTER BY

distribute by:按照指定的欄位或表示式對資料進行劃分,輸出到對應的Reduce或者檔案中。
cluster by:除了兼具distribute by的功能,還兼具sort by的排序功能。

##distribute by

  1. hive>set mapred.reduce.tasks=2;
  2. hive>INSERT overwrite LOCAL directory '/tmp/lxw1234/'
  3. SELECT id FROM lxw1234_com
  4. distribute BY id;

執行後在本地的/tmp/lxw1234目錄中生成了000000_0和000001_0兩個檔案:
cat 000000_0
8
2
6
cat 000001_0 ##id%2=1的記錄
1
9
3
5

##cluster by

  1. hive>set mapred.reduce.tasks=2;
  2. hive> INSERT overwrite LOCAL directory '/tmp/lxw1234/'
  3. SELECT id FROM lxw1234_com
  4. CLUSTER BY id;
  5. cat 000000_0
  6. 2
  7. 6
  8. 8
  9. cat 000001_0
  10. 1
  11. 3
  12. 5
  13. 9

注意:使用cluster by之後,每個檔案中的id都進行了排序,而distribute by沒有。

8.4 子查詢

子查詢和標準SQL中的子查詢語法和用法基本一致,需要注意的是,Hive中如果是從一個子查詢進行SELECT查詢,那麼子查詢必須設定一個別名。

  1. SELECT col
  2. FROM (
  3. SELECT a+b AS col
  4. FROM t1
  5. ) t2

另外,從Hive0.13開始,在WHERE子句中也支援子查詢,比如:

  1. SELECT *
  2. FROM A
  3. WHERE A.a IN (SELECT foo FROM B);
  4. SELECT A
  5. FROM T1
  6. WHERE EXISTS (SELECT B FROM T2 WHERE T1.X = T2.Y)

還有一種將子查詢作為一個表的語法,叫做Common Table Expression(CTE):

  1. with q1 as(select*from src where key='5'),
  2. q2 as(select*from src s2 where key ='4')
  3. select*from q1 union all select*from q2;
  4. with q1 as(select key, value from src where key ='5')
  5. from q1
  6. insert overwrite table s1
  7. select*;

8.5 虛擬列

Hive查詢中有兩個虛擬列:
INPUT__FILE__NAME:資料對應的HDFS檔名;
BLOCK__OFFSET__INSIDE__FILE:該行記錄在檔案中的偏移量;

  1. hive>select id,INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE from lxw1234_com;
  2. 5 hdfs://cdh5/tmp/lxw1234/1.txt 0
  3. 3 hdfs://cdh5/tmp/lxw1234/1.txt 2
  4. 6 hdfs://cdh5/tmp/lxw1234/1.txt 4
  5. 2 hdfs://cdh5/tmp/lxw1234/1.txt 6
  6. 9 hdfs://cdh5/tmp/lxw1234/1.txt 8
  7. 8 hdfs://cdh5/tmp/lxw1234/1.txt 10
  8. 1 hdfs://cdh5/tmp/lxw1234/1.txt 12