简化示例:
在 hive 里,我有一张table t
有两列:
Name, Value
Bob, 2
Betty, 4
Robb, 3
我想做一个 case when
使用值列的总和:
Select
Name
, CASE
When value>0.5*sum(value) over () THEN ‘0’
When value>0.9*sum(value) over () THEN ‘1’
ELSE ‘2’
END as var
From table
我不喜欢这样的事实 sum(value) over ()
计算两次。有没有办法只计算一次。添加了twist,我想在一个查询中实现这一点,因此不需要声明用户变量。
我在考虑标量查询:
With total as
(Select sum(value) from table)
Select
Name
, CASE
When value>0.5*(select * from total) THEN ‘0’
When value>0.9*(select * from total)THEN ‘1’
ELSE ‘2’
END as var
From table;
但这行不通。
tldr:有没有一种方法可以在没有用户变量的情况下简化第一个查询?
3条答案
按热度按时间4szc88ey1#
交叉联接将总和提取到表中的子查询:
并更改case表达式中when子句的顺序,因为这样,第二个case就永远不会成功。
p1iqtdky2#
别担心这个。让优化器来操心吧。但是,如果不想重复表达式,可以使用子查询或cte:
9gm1akwq3#
由于i/o是减慢配置单元查询速度的主要因素,因此我们应该努力减少阶段数以获得更好的性能。
所以最好不要在这里使用子查询或cte。
使用全局窗口子句尝试此sql:
在这种情况下
window clause
是减少代码重复的推荐方法。Windows和Windows
sum
聚合将只计算一次。你可以跑了explain select...
,确认只会启动一个有意义的mr阶段。编辑:
1.一个简单的
select
子查询上的子句不值得担心。它可以下推到子查询的最后一个阶段,以避免额外的mr阶段。2.驻留在同一查询块中的两个相同聚合将只计算一次。所以不要担心潜在的重复计算。