ApacheHive不同的查询联合,在同一个表上,在每个查询中使用不同的where条件?

p1iqtdky  于 2021-05-30  发布在  Hadoop
关注(0)|答案(3)|浏览(299)

我有一个名为“sales”的配置单元表,其结构如下:

id,ptype,amount,time,date
1,a,12,2240,2013-12-25
1,a,4,1830,2013-12-25
1,b,2,1920,2013-12-25
1,b,3,2023,2013-12-25
2,a,5,1220,2013-12-25
2,a,1,1320,2013-12-25

下面是我对不同变量的查询:

Q1: select id,sum(amount) as s_amt from sales group by id;
Q2: select id, sum(amount) as s_a_amt from sales where ptype='a' group by id;
Q3: select id, sum(amount) as s_b_amt from sales where ptype='b' group by id;

就我在hive中了解到的,只有当我们有相同的列名或查询模式时,我们才能应用“unionall”选项。下面是我希望使用配置单元查询实现的最终结果:

id,s_amt,s_a_amt,s_b_amt
1,21,16,5
2,6,6,0

下面是一个我尝试过并成功执行的查询。但是,当您必须为300多个变量设计相同的查询时,这将是一项非常痛苦的任务。考虑到我们有300多个变量,有没有有效的方法来完成同样的任务?感谢您的评论!

select t.id,max(t.s_amt) as s_amt,max(t.s_a_amt) as s_a_amt, max(t.s_b_amt) as s_b_amt
  from
     (select s1.id,sum(amount) as s_amt,0 as s_a_amt,0 as s_b_amt from sales s1 group by id union all
     select s2.id, 0 as s_amt, sum(amount) as s_a_amt, 0 as s_b_amt from sales s2 where ptype='a' group by id union all
     select s3.id, 0 as s_amt,0 as s_a_amt, sum(amount) as s_b_amt from sales s3 where ptype='b' group by id) t
group by t.id;
whlutmcx

whlutmcx1#

hive最近添加了分组集作为一项新功能(https://issues.apache.org/jira/browse/hive-3471). 它可能比mqt更容易(写或读)。但并不是每个人都知道这个特性,case函数的使用,正如arnaud所说明的,在实践中更常用。

ztigrdn8

ztigrdn82#

理想的解决办法是
ibm所指的具体化查询表(mqt)。
摘要表是MQT的特殊形式,这正是您所需要的。快速定义—顾名思义,mqt是一个简单的摘要表,具体化在磁盘上。
使用mqt支持,您只需执行以下操作

CREATE MATERIALISED QUERY TABLE MQTA AS (
select id, sum(amount) as s_a_amt from sales where ptype='a' group by id;
)
Data initially deferred 
Refresh deferred
Maintained by User

最初延迟的数据表示不在摘要表中插入摘要记录。refresh deferred表示可以随时使用refresh table语句刷新表中的数据。由用户维护表示此表的引用必须由用户负责-由系统维护是另一个选项,在该选项中,当基表看到insert/deletes//更新时,系统负责自动更新摘要表。
您可以像简单的select查询一样直接查询mqt,所有繁重的汇总记录实际上都是在查询mqt之前运行的,而不是在查询mqt时运行的,因此它会更快。
但是afaik配置单元不支持mqt或摘要表。
现在您知道了这个概念,只需简单地模拟一下即可。创建一个摘要表并插入摘要记录(刷新表概念)。您必须通过控制某种上次加载日期字段定期加载摘要值,以便仅在上次刷新后拾取记录。您可以使用计划作业配置单元脚本来执行此操作。

INSERT INTO PTYPE_AMOUNT_MQT AS (
select *
  from
     (select s1.id,sum(amount) as s_amt,0 as s_a_amt,0 as s_b_amt from sales s1 where record_create_date > last_Refresh_date group by id union all
     select s2.id, 0 as s_amt, sum(amount) as s_a_amt, 0 as s_b_amt from sales s2 where ptype='a' and record_create_date > last_Refresh_date  group by id union all
     select s3.id, 0 as s_amt,0 as s_a_amt, sum(amount) as s_b_amt from sales s3 where ptype='b'  and record_create_date > last_Refresh_date group by id) 
)

像record\u create\u date和time这样的审核字段总是很好的。last\u refresh\u date是作业运行的最后一次

osh3o9ms

osh3o9ms3#

解决方案应该是:

select id, sum(amount) s_amt, 
        SUM (CASE WHEN ptype='a' THEN amount 
                       ELSE 0
        END) sum_a_amt,
        SUM (CASE WHEN ptype='b' THEN amount 
                       ELSE 0
        END) sum_b_amt
from sales 
group by id;

请尝试一下,告诉我如果它工作,我不能测试它现在。。。

相关问题