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 使用注意事项
不管是哪个版本,使用的注意事项是相同的。
- 需要保证select中字段须一致,每个select语句返回的列的数量和名字必须一样,否则会报错。在1.2.1后的版本中对应列名不一致也不报错,例如我提供的虚拟机中的Hive……但仍然建议列名保持一致;
- 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