Hive: lateral view 用法

lateral view 的语法格式

lateralView: 
LATERAL VIEW udtf(expression) tableAlias AS columnAlias (',' columnAlias)* 
fromClause: FROM baseTable (lateralView)*

用法描述

lateral view 要与UDTF函数一起使用,比如 explode() 函数。这里的UDTF函数是指用户自定义的表生成函数(英文全称:user defined table-generating functions),它可以接受一行输入然后产生0行或多行输出。

lateral view 首先将utdf函数应用到每一行上,这时每一行经utdf处理后得到多行输出,这些输出将会组建成一张虚拟表,然后这张虚拟表会跟当前表进行join操作,join完成之后会得出一张结果虚拟表,这张结果表里就有了utdf生成的列,当然原表的列除了utdf消耗的列之外肯定也在都里面。

示例说明

考虑下面这张 pageAds 表:

Column name

Column type

page_id

String

adid_list

Array<int>

里面有两行数据:

page_id

adid_list

front_page

[1,2,3]

contact_page

[3,4,5]

这两行数据的意思是:front_page页有三条广告,id分别是1,2,3。contact_page页也有三条广告,id分别是3,4,5。

现在需要解决的问题是:在所有页面中统计每条广告出现的次数,输出广告id和该广告出现的总次数。

第一步:

使用 lateral view 和 explore() 函数将 adid_list 列的 list 拆分,sql代码如下:

SELECT page_id, ad_id 
FROM pageAds 
LATERAL VIEW explode(adid_list) adTable AS ad_id;

可以得到以下结果:

page_id (string)

adid (int)

"front_page"

1

"front_page"

2

"front_page"

3

"contact_page"

3

"contact_page"

4

"contact_page"

5

然后我们再使用 count/group by 语句统计出每个adid出现的次数:

SELECT ad_id, count(1) 
FROM pageAds 
LATERAL VIEW explode(adid_list) adTable AS ad_id 
GROUP BY ad_id

得到最终结果:

ad_id

count(1)

1

1

2

1

3

2

4

1

5

1

Multiple Lateral Views

一个FROM子句可以包含多个LATERAL VIEW子句。 后续的LATERAL VIEW可以从出现在LATERAL VIEW左侧的任何表中引用列。

具体案例:

SELECT * 
FROM exampleTable 
LATERAL VIEW explode(col1) myTable1 AS myCol1 
LATERAL VIEW explode(myCol1) myTable2 AS myCol2;

实例表格:

Array<int> col1

Array<string> col2

[1, 2]

[a", "b", "c"]

[3, 4]

[d", "e", "f"]

得到结果:

int myCol1

string myCol2

1

"a"

1

"b"

1

"c"

2

"a"

2

"b"

2

"c"

3

"d"

3

"e"

3

"f"

4

"d"

4

"e"

4

"f"

outer lateral views

later view 前面还可以加上一个 outer 关键字,这是为了避免 当udtf 没有得到任何结果时最终虚拟结果表里丢失原数据行的问题。具体来将,由于later view 的工作原理是将原表与 udtf 产生的虚拟表做 inner join 操作,所以如果 udtf 不产生任何结果时,那么对应原表的那一行也会在 inner join 操作后消失。outer关键字就是来解决这个问题的,加上这个关键字之后执行的就是 outer join 操作了,因此原表数据会被完全保留下来。

例如,上面的 pageAds 表中如果有以下三行数据:

page_id

adid_list

front_page

[1,2,3]

contact_page

[3,4,5]

end_page

[ ]

那么执行 lateral view 的sql:

SELECT page_id, ad_id 
FROM pageAds 
LATERAL VIEW explode(adid_list) adTable AS ad_id;

得到的结果将会是:

page_id (string)

adid (int)

"front_page"

1

"front_page"

2

"front_page"

3

"contact_page"

3

"contact_page"

4

"contact_page"

5

可以看到,end_page 那一行消失了,因为它没有在 inner join 中关联到任何数据。因此如果想保留原表全部数据的话,就需要加上outer关键字:

SELECT page_id, ad_id 
FROM pageAds 
OUTER LATERAL VIEW explode(adid_list) adTable AS ad_id;

得到如下结果

page_id (string)

adid (int)

"front_page"

1

"front_page"

2

"front_page"

3

"contact_page"

3

"contact_page"

4

"contact_page"

5

“end_page”

<NULL>