HIVE LanguageManual Select

select語法

select完整的語法結構如下


[WITH CommonTableExpression (, CommonTableExpression)*]    (Note: Only available starting with Hive 0.13.0)
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 [offset,] rows]
  • select語句可以是union語句的一部分,也可以是另一個query語句的subquery。
  • table_reference表示query的輸入。可以是table、view、join構造的語句或subquery
  • 表名和列名都是不區分大小寫。

如最簡單的查詢,查詢t1表的所有數據

SELECT * FROM t1;
# 查看當前使用的數據庫
SELECT current_database();
# 使用default數據庫
use default;

where語句

where條件是一個布爾表達式。hive支持在where條件裏用UDF。也支持subquery。

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

ALL and DISTINCT 語句

ALL and DISTINCT是決定重複的行是否全部返回。如果沒有顯示指定的話,默認匹配到的行全部返回。DISTINCT就是去重的意思。這和sql語法是保持一致的。Hive從1.1.0版本開始支持SELECT DISTINCT *

Partition Based Queries

通常,一個query語句都會scan整張表(sampling取樣除外)。如果一個表是分區表,那麼可以採用分區裁剪的方式只需要去scan某些分區數據而不用scan整張表就可以了。
如果Partition的列在where語句中或者join的on語句中出現,那麼Hive就可執行分區裁剪。
例如,page_views表以date這列做的分區,那麼下面的query獲取date在2008-03-01 and 2008-03-31之間的數據,那麼此時Hive就可以使用分區裁剪加快查詢。

SELECT page_views.*
FROM page_views
WHERE page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31'

如果page_views表和dim_users表在join,你可以在on語句裏確定Partition的範圍,例如

SELECT page_views.*
FROM page_views JOIN dim_users
  ON (page_views.user_id = dim_users.id AND page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31')
Partition Filter Syntax

假如一個表有兩個分區列country和state。考慮下面的過濾條件。

country = "USA" AND (state = "CA" OR state = "AZ")

支持以下幾種分區裁剪語法

  • =
  • <
  • <=
  • >
  • >=
  • <>
  • AND
  • OR
  • LIKE (on keys of type string only, supports literal string template with ‘.*’ wildcard)

Group By

完整的語法如下

groupByClause: GROUP BY groupByExpression (, groupByExpression)*
 
groupByExpression: expression
 
groupByQuery: SELECT expression (, expression)* FROM src groupByClause?

例如,根據gender分組,然後select語句裏做聚合輸出如sum、count等。和sql語法一樣,用了group by之後select語句裏是不能含有除聚合和group by字段外的其他字段的。

SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(*), sum(DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;
Map-side Aggregation for Group By

關於group by有一個優化的地方就是,可以在map端開啓部分聚合提高效率的同時也耗費了更多的內存。類似於MapReduce中的combiner。

set hive.map.aggr=true;

Order By

完整的語法如下,和sql的語法是類似的。

colOrder: ( ASC | DESC )
colNullOrder: (NULLS FIRST | NULLS LAST)           -- (Note: Available in Hive 2.1.0 and later)
orderBy: ORDER BY colName colOrder? colNullOrder? (',' colName colOrder? colNullOrder?)*
query: SELECT expression (',' expression)* FROM src orderBy

hive.mapred.mode=strict嚴格模式下,order by後面最好跟limit。這是因爲order by是對該表所有的數據進行完整的排序,將會有一個reducer來對所有的數據進行排序。如果表很大的話,那麼這個reducer就需要很久才能排序完。

Sort By 和 Distribute By

Sort By完整的語法如下,和order by類似
Sort By一般和Distribute By一起用,Distribute By做數據的分發,Sort By對每個reducer的數據做排序。

colOrder: ( ASC | DESC )
sortBy: SORT BY colName colOrder? (',' colName colOrder?)*
query: SELECT expression (',' expression)* FROM src sortBy

在發送數據給每個reducer之前,Hive會對數據基於SORT BY的字段進行排序。排序規則是根據SORT BY的字段來定義的,如果字段是數字那麼就按照數字排序,如果字段是string就按照字母排序

Difference between Sort By and Order By

Sort ByOrder By的主要區別在於,Sort By保證每個reducer的數據是排好序的,Order By是保證數據在全局都是排好序的(因爲Order By只有一個reducer)。如果有多個reducer的話,Sort By只能是保證reducer內數據有序即部分有序。
例如,給定如下hql語句,先是對key做升序,再對value做降序。

SELECT key, value FROM src SORT BY key ASC, value DESC

如果查詢有兩個reducer,那麼每個reducer的輸出如下所示

0   5
0   3
3   6
9   1
0   4
0   3
1   1
2   5
Setting Types for Sort By

在做完一個transformation之後,變量類型通常都會被當做string,即數字類型的數據可能會按照字典順序排序。爲了解決這個問題,我們在第二個select的sort by的時候需要用cast轉換爲原來的類型。
例如,下面的sql所示 cast(value as double) AS value


FROM (FROM (FROM src
            SELECT TRANSFORM(value)
            USING 'mapper'
            AS value, count) mapped
      SELECT cast(value as double) AS value, cast(count as int) AS count
      SORT BY value, count) sorted
SELECT TRANSFORM(value, count)
USING 'reducer'
AS whatever

Cluster By and Distribute By

Cluster By的作用等同於Distribute By + Sort By
Hive使用Distribute By在reducer間分發數據。有相同Distribute By列的值的row會發送給同一個reducer。然而,Distribute By並不會保證reducer裏的數據是排好序的。
例如,我們使用Distributing By x給下面5條數據分發到2個reducer上。

x1
x2
x4
x3
x1

reducer-1可能獲取下面的數據

x1
x2
x1

reducer-2可能獲取下面的數據

x4
x3

注意,上面相同的x=x1的數據都發到同一個reducer上了,但是並沒有排序。

相反,如果我們使用Cluster By x,那麼會在分發數據之後對數據基於x排序。
reducer-1獲取的數據如下

x1
x1
x2

reducer-2獲取的數據如下

x3
x4

如果我們使用Distribute By and Sort By的話,partition columnssort columns就可以是不同的字段。
例如

SELECT col1, col2 FROM t1 CLUSTER BY col1
SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC

Having語句

Hive從0.7.0版本開始支持Having語句,和sql的用法是一樣的,都是在分組後進行過濾的。
如下所示

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

Hive 0.7.0版本前可以通過subquery的方式實現類似Having的功能

SELECT col1 FROM (SELECT col1, SUM(col2) AS col2sum FROM t1 GROUP BY col1) t2 WHERE t2.col2sum > 10

Limit語句

limit限制select語句返回的行數。
它支持一個參數也支持兩個參數。
如果是兩個參數的話,第一個參數是第一條數據的offset值,第二個參數是最多返回的數據行數。
如果是一個參數的話,默認第一條數據的offset就是0,這個參數表示最多返回的數據行數。

例如,下面的sql表示返回排序完成後前5條數據

SELECT * FROM customers ORDER BY create_date LIMIT 5

例如,下面的sql表示返回第3到第7總共5條的數據

SELECT * FROM customers ORDER BY create_date LIMIT 2,5

UNION語句

完整語法如下,select_statement最好用括號()括起來。
UNION ALLUNION DISTINCT是可以混用的。但是UNION DISTINCT會覆蓋掉它左邊所有的UNION ALL

select_statement UNION [ALL | DISTINCT] select_statement UNION [ALL | DISTINCT] select_statement ...

Hive1.2版本之後默認是DISTINCT。如下圖
在這裏插入圖片描述
例如下面的sql

SELECT u.id, actions.date
FROM (
    SELECT av.uid AS uid
    FROM action_video av
    WHERE av.date = '2008-06-03'
    UNION ALL
    SELECT ac.uid AS uid
    FROM action_comment ac
    WHERE ac.date = '2008-06-03'
 ) actions JOIN users u ON (u.id = actions.uid)
Unions in DDL and Insert Statements

Union可用於viewinsertCTAS(create table as select)語句。

Column Aliases for Schema Matching

UNION期望表達式的兩邊都是同樣的schema。
例如下面的query就會報錯"FAILED: SemanticException 4:47 Schema of both sides of union should match."

INSERT OVERWRITE TABLE target_table
  SELECT name, id, category FROM source_table_1
  UNION ALL
  SELECT name, id, "Category159" FROM source_table_2

這種情況下,我們應該講schema轉換成一樣的

INSERT OVERWRITE TABLE target_table
  SELECT name, id, category FROM source_table_1
  UNION ALL
  SELECT name, id, "Category159" as category FROM source_table_2
Column Type Conversion

scheme必須相同,那麼column的類型也必須是相同的。
例如,可以使用caststring類型轉換成data類型保持schema一致。

SELECT name, id, cast('2001-01-01' as date) d FROM source_table_1
UNION ALL
SELECT name, id, hiredate as d FROM source_table_2

SubQuery

子查詢,和sql的子查詢是類似的。
可以用在from語句和where語句裏 ,但是不能將subquery作爲projection來返回,但是sql裏是支持的,如下圖所示。

sql支持subquery作爲projection來返回。
在這裏插入圖片描述
hive是不支持subquery作爲projection來返回的。

0: jdbc:hive2://master:10000> select ct,(select company from company limit 1) as c from company;
Error: Error while compiling statement: FAILED: SemanticException org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSubquerySemanticException: Unsupported SubQuery Expression Invalid subquery. Subquery in SELECT could only be top-level expression (state=42000,code=40000)
0: jdbc:hive2://master:10000>
Subqueries in the FROM Clause

完整的語法如下

SELECT ... FROM (subquery) name ...
SELECT ... FROM (subquery) AS name ...   (Note: Only valid starting with Hive 0.13.0)

例如,下面的subquery

SELECT t3.col
FROM (
  SELECT a+b AS col
  FROM t1
  UNION ALL
  SELECT c+d AS col
  FROM t2
) t3
Subqueries in the WHERE Clause

支持INNOT IN

SELECT *
FROM A
WHERE A.a IN (SELECT foo FROM B);

支持EXISTSNOT EXISTS

SELECT A
FROM T1
WHERE EXISTS (SELECT B FROM T2 WHERE T1.X = T2.Y)

Virtual Columns

INPUT__FILE__NAME 表示map task的輸入文件名
BLOCK__OFFSET__INSIDE__FILE表示the current global file position

如下圖
在這裏插入圖片描述
Hive0.8版本後還增加了如下四個

ROW__OFFSET__INSIDE__BLOCK
RAW__DATA__SIZE
ROW__ID
GROUPING__ID

Common Table Expression

Common Table Expression(CTE)是在with語句中的臨時結果數據集,應放在selectinsert關鍵字之前。一個或多個CTEs可以用在Hive的SELECT, INSERT, CREATE TABLE AS SELECT, or CREATE VIEW AS SELECT等語句裏。

完整的語法如下

withClause: cteClause (, cteClause)*
cteClause: cte_name AS (select statment)

下面是一些例子。

with q1 as ( select key from src where key = '5')
select *
from q1;

-- chaining CTEs
with q1 as ( select key from q2 where key = '5'),
q2 as ( select key from src where key = '5')
select * from (select key from q1) a;
  
-- union example
with q1 as (select * from src where key= '5'),
q2 as (select * from src s2 where key = '4')
select * from q1 union all select * from q2;

-- ctas example
create table s2 as
with q1 as ( select key from src where key = '4')
select * from q1;

參考網址

LanguageManual+Select
Partition+Filter+Syntax
LanguageManual+GroupBy
LanguageManual+SortBy
LanguageManual+Union
LanguageManual+SubQueries
LanguageManual+VirtualColumns
Common+Table+Expression

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章