其他分享
首页 > 其他分享> > Hive零基础从入门到实战 入门篇(二十) HiveQL:UNION ALL语句

Hive零基础从入门到实战 入门篇(二十) HiveQL:UNION ALL语句

作者:互联网

前言

上篇博客入门篇(十九)介绍的JOIN语句是将多个表的列 ‘横向合并’,本篇要介绍的UNION ALL语句则是将多个表的列纵向合并,相当于将多个表的数据直接摞在一起,下面我们来详细介绍UNION ALL语句的用法。

 

1. 语法

1.1 Hive1.2.0后的语法

Hive1.2.0之后版本的语法如下:

SELECT * FROM a

UNION [ALL] 

SELECT * FROM b

UNION [ALL] 

SELECT * FROM c 
…

[]中的ALL是可选项,使用UNION时会对最后合并的数据进行去重,使用UNION ALL则只合并不去重。

但是!

我至今没有见过公司使用Hive1.2.0之后的版本……常见的Hive版本在0.13.0之后,1.1.0之前。

 

1.2 Hive0.13.0到1.1.0的语法

语法如下:

SELECT * FROM a

UNION ALL

SELECT * FROM b

UNION ALL

SELECT * FROM c 
…

也就是说目前在绝大多数公司的Hive中只支持UNION ALL,不支持去重的UNION操作,想要去重需要自己使用子查询,套一层使用DISTINCT或者GROUP BY进行去重。

在0.13.0之后所有的版本中UNION ALL即可以在顶级查询中使用,也可以在子查询中使用。

而在0.13.0之前的版本,也就是从0.12.0往前,UNION ALL都只能在子查询中使用,否则会报错。

 

1.3 Hive0.12.0前的语法

语法如下:

​SELECT * 
FROM(
     SELECT * FROM a
     
     UNION ALL
     
     SELECT * FROM b
     
     UNION ALL
     
     SELECT * FROM c 
     …
    )

 

1.4 使用注意事项

不管是哪个版本,使用的注意事项是相同的。

  1. 需要保证select中字段须一致,每个select语句返回的列的数量和名字必须一样,否则会报错。在1.2.1后的版本中对应列名不一致也不报错,例如我提供的虚拟机中的Hive……但仍然建议列名保持一致
  2. ORDER BY、CLUSTER BY、DISTRIBUTE BY、SORT BY、LIMIT这些语句不能在UNION ALL中单独的查询中使用,前四个排序语句必须括起来使用子查询后使用,LIMIT语句则可以先使用WITH AS语句在各自的查询中查好,最后再UNION ALL。例如下面的写法会报错:
SELECT * FROM a limit 1

UNION ALL

SELECT * FROM b limit 1

UNION ALL

SELECT * FROM c limit 1
…

   3. Hive中有数据格式的隐式转换,所以不强制要求所有对应列的数据格式是相同的。

 

2 举例

2.1 注意事项1举例

UNION ALL时字段数量如果不一样,会报错,这里我们自定义两个字段num1、num2进行演示:

WITH a
AS (
      SELECT 1 num1
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 LIMIT 1
      )
      ,b
AS (
      SELECT 1 num1
            ,2 num2
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 LIMIT 1
      )
SELECT *
FROM a

UNION ALL

SELECT *
FROM b;

运行报错如下:

FAILED: SemanticException Schema of both sides of union should match.

 

UNION ALL时对应的列名如果不一样,1.2.1前的版本会报错,这里我们自定义字段num1、num2、num3进行演示:

WITH a
AS (
      SELECT 1 num1
            ,2 num2
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 limit 1
      )
      ,b
AS (
      SELECT 1 num1
            ,3 num3
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 limit 1
      )
SELECT *
FROM a

UNION ALL

SELECT *
FROM b;

我提供的虚拟机中的Hive(1.2.1)不会报错,不过因为公司的版本一般都比较老,So这样的写法在工作中的环境报错如下:

FAILED: SemanticException 19:5 Schema of both sides of union should match. _u1-subquery2 does not have the field num2. Error encountered near token 'b'

所以还是强烈建议直接将列名改为一致,如下:

WITH a
AS (
      SELECT 1 num1
            ,2 num2
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 limit 1
      )
      ,b
AS (
      SELECT 1 num1
            ,3 num2
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 limit 1
      )
SELECT *
FROM a

UNION ALL

SELECT *
FROM b;

 

2.2 注意事项2举例

分别查询表t_od_use_cnt中的20190101、20190102、20190103三天的一条记录,使用UNION ALL将三条记录合并。

SELECT *
FROM app.t_od_use_cnt
WHERE date_8 = 20190101 limit 1

UNION ALL

SELECT *
FROM app.t_od_use_cnt
WHERE date_8 = 20190101 limit 1

UNION ALL

SELECT *
FROM app.t_od_use_cnt
WHERE date_8 = 20190101 limit 1;

这种写法违反了上面的第三条注意事项,报错如下:

FAILED: ParseException line 11:0 Failed to recognize predicate 'UNION'. Failed rule: 'orderByClause clusterByClause distributeByClause sortByClause limitClause can only be applied to the whole union.' in statement

正确的写法如下:

WITH a
AS (
      SELECT *
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190101 limit 1
      )
      ,b
AS (
      SELECT *
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190102 limit 1
      )
      ,c
AS (
      SELECT *
      FROM app.t_od_use_cnt
      WHERE date_8 = 20190103 limit 1
      )
SELECT * FROM a

UNION ALL

SELECT * FROM b

UNION ALL

SELECT * FROM c;

运行结果如下:

_u1.platform	_u1.app_version	_u1.user_id	_u1.use_cnt	_u1.is_active	_u1.date_8
1	1.5	10000	6	1	20190101
1	1.4	10200	46	1	20190102
2	1.2	10400	40	1	20190103

 

标签:cnt,HiveQL,UNION,app,use,Hive,limit,SELECT
来源: https://blog.csdn.net/qq_23897391/article/details/92803543