Hive語法:union

Hive語法:union

1、介紹

本文參考官方介紹,原文地址以下: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Unionsql

Hive官方提供了一種聯合查詢的語法,原名爲Union Syntax,用於聯合兩個表的記錄進行查詢,此處的聯合和join是不一樣的,join是將兩個表的字段拼接到一塊兒,而union是將兩個表的記錄拼接在一塊兒。apache

通俗來說,join是用於左右拼接,而union是用於上下拼接。架構

好比有以下兩個表: 表1:ide

id username
1 user001
2 user002

表2:測試

id username
1 user003
2 user004

join的左右拼接如這樣:ui

id username id username
1 user001 1 user003
2 user002 2 user004

unoin的上下拼接如這樣:.net

id username
1 user001
2 user002
1 user003
2 user004

2、語法

官方語法:code

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

union用於將多個select語句的結果組合到單個結果集中。orm

須要注意:blog

  • 1.2.0以前的Hive版本僅支持union all,其中不會刪除重複行。
  • 在Hive1.2.0##及更高版本中,union的默認行爲是從結果中刪除重複的行。可選的distinct關鍵字指定了刪除重複行。使用可選的all關鍵字,不會發生重複行刪除,結果包含select語句中的全部匹配行。
  • 能夠在同一查詢中混合使用union all和union distinct。
  • 每一個select語句返回的列的數量和名稱必須相同,不然,將引起架構錯誤。錯誤內容以下:SemanticException Schema of both sides of union should match.

3、應用

一、from子句

union語句能夠做爲form的子句進行使用,簡單示例以下:

select * form ( select_statement union all select_statement ) unionResult

以下是官方示例:

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)

二、DDL和插入語句

union能夠在視圖,插入和CTAS(create table as select)語句中使用。查詢能夠包含多個union子句。

三、應用於從句

要將order by,sort by,cluster by,distribute by 或limit 應用於union兩邊的select語句中也是能夠的,以下:

SELECT key FROM (SELECT key FROM src ORDER BY key LIMIT 10)subq1
UNION
SELECT key FROM (SELECT key FROM src1 ORDER BY key LIMIT 10)subq2

要將以上應用於union以後的最終結果也是能夠的,示例以下:

SELECT key FROM src
UNION
SELECT key FROM src1 
ORDER BY key LIMIT 10

四、字段別名應用

union要求表達式兩側的字段名稱以及字段數量都必須相同,這種狀況下,有些表字段的含義相等,可是字段名稱不一樣的狀況,使用union就會出現報錯。union支持字段別名相等。

以下示例:

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

上述語句會報錯。

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

上述語句可正常執行。

五、字段類型轉換

Hive2.2.0版本的HIVE-14251中,Hive支持在每一個類型組中執行隱式轉換,包括字符串、數字、日期等。爲了組合來自不一樣組的類型,在查詢中須要顯式強制轉換。

示例以下:

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

4、案例

本人本身尋找了一個使用此語法的案例,這裏和你們進行分享。若有錯誤敬請指正。

一、要求

存在兩張用戶表,一張爲歷史表,一張爲當日表,天天要將當日表中的數據和歷史表中的數據進行去重合併到新的歷史表中。

二、思路

這裏本人首先想到的步驟是,將兩張表的數據進行合併,而後查詢全部去重存入另一張表。 這個思路的實現侷限於hive的版本,這裏提供兩個版本的,兩種方式進行實現,更高的2.2.0版本,本人沒有使用,這裏使用的兩個版本分別是CDH中集成的hive1.1.0版本和開源的hive1.2.0版本。

三、準備

建立三張表:

  • user01:表明歷史表
  • user02:表明當日表
  • user03:表明最後合併的歷史表。

建表語句:

create external table user01(id int, username string) row format delimited fields terminated by '|' location 'hdfs://192.168.75.150:9000/test/user1';

create external table user02(id int,username string) row format delimited fields terminated by '|' location 'hdfs://192.168.75.150:9000/test/user2';

爲了方便構造數據,本人將兩個有數據的表建立成外部表,將最後的結果表建立成內部表。

create table user03(id int,username string) row format delimited fields terminated by '|';

user01表的數據內容:

1|user001
2|user002
3|user003
4|user004

user02表的數據內容:

1|user002
2|user006
3|user007
4|user009
5|user003

四、合併數據

在提取數據以前先來作個測試,以下的測試環境是Hive1.2.0版本:

select * from user01 union select * from user02;

結果以下圖:

select username from user01 union select username user02;

結果以下圖:

第三個語句和結果以下圖:

從上述的實驗,咱們能夠看出:

  • 1.unoin去重的根據是把要展現的全部字段做爲一個總體來去重的。
  • 2.unoin左右兩邊的字段結構要相同,此相同包括名稱和個數,這個上面介紹已經說過了。
  • 3.unoin左右兩邊的字段結構不一樣就會報錯。

1.方法一

此方式採用的是CDH5.7中集成的Hive1.1.0版本實現。 這裏能夠一條HQL實現,HQL以下:

insert overwrite table user03 
select row_number() over() as id ,username from (
select distinct(username) as username from (
select username from user01 union all select username from user02) as A) as B;

這裏須要說一下,去重的那一步,必須單獨寫,沒辦法加id,加上就報錯,因此又在外面加了一層加ID的查詢,而後再插入。

查詢結果以下:

2.方法二

採用開源的Hive1.2.0版本進行,這裏就比上面要簡單多了,由於可使用去重了!

insert overwrite table user03 
select row_number() over() as id,username from (
select username from user01 union select username from user02) as A;

查詢結果以下:

以上就是案例的整個過程!

上一篇:Hive應用:選取分隔符

下一篇:Hive應用:explode和lateral view

相關文章
相關標籤/搜索