zoukankan      html  css  js  c++  java
  • Hive学习小记-(6)collect_set与笛卡尔积使用

     场景

    有两张表,一张活动清单表actv_evt:记录了所有的活动,包括活动id,活动名称及活动相关配置信息;一张客户活动参与表cust_actv,记录了客户参与活动信息。

    cust_actv中参与了活动的客户定义为活跃客户,现在公司想对活跃客户做推广,将没参与过的活动推送给他们

    举例:共有actv1, actv2, actv3, actv4,客户cust1参与了actv2, actv4,客户cust2参与了actv1,那么需要找出这样的目标数据:

    cust1:actv1,actv3

    cust2:actv2,actv3,actv4

    原脚本

    -- 5.按uid,通过collect_set将每个客户未参加的活动行程组合,如cust1,[actv1, actv3]
    select 
         a.cust_uid
        ,concat_ws(',',collect_set(concat_ws(':',actv_id,actv_nm))) as actv
    from (
        -- 4.拿步骤3做出来的全客户全活动对应表与b表关联,关联不上的数据就是cust_uid未真实参加的活动,如cust1对应没关联上的记录为cust1,actv1;cust1,actv3
        select
             a.actv_id,a.actv_nm,a.cust_uid
        from (
            -- 3.每个活跃客户与每个活动做笛卡尔积,数据量会很大,目的是做出每个客户与每个活动对应的数据,如对客户1:cust1,actv1;cust1,actv2;cust1,actv3;cust1,actv4
            select
                 a.actv_id,a.actv_nm,b.cust_uid
            from (
                -- 2.筛出所有活动清单
                select distinct a.actv_id,a.actv_nm from tb_actv_evt
            ) as a
            left join (
                    -- 1.筛选出活跃客户
                    select distinct cust_uid from tb_cust_actv
                    ) as b
            on 1=1  --笛卡尔积
        ) as a
        left join tb_cust_actv as b
        on a.actv_id=b=actv_id
        and a.cust_uid=b.cust_uid
        where b.actv_id is null
    ) as a
    group by cust_uid

    优化一:

    可以看出原脚本第1、2步骤两个distinct,3笛卡尔积是消耗资源多的点。本题的笛卡尔积不可避免,但可以减少笛卡尔积的数据量。

    -- 3.拿步骤2的所有活动与步骤1参与的活动做差集运算
    select 
         b.cust_uid
        ,a.actv_all-b.actv_usd   -- 这里指的是差集运算
    from (
    -- 1.筛选出活跃客户参与过的活动清单.如客户1:cust1,[actv2, actv4]
        select 
             cust_uid 
            ,collect_set(concat_ws(':',b.actv_id,b.actv_nm) as actv_usd
        from tb_cust_actv as b
        group by cust_uid 
        ) as b
    left join (
    -- 2.筛出所有活动清单,即[actv1, actv2, actv3, actv4],这时候再笛卡尔积其实相当于b表中每条客户数据只需要与[actv1,actv2,actv3,actv4]这一条数据笛卡尔积
        select 
             collect_set(concat_ws(':',a.actv_id,a.actv_nm) as actv_all
        from tb_actv_evt
        -- group by collect_set(concat_ws(':',a.actv_id,a.actv_nm) collect_set是类似sum,avg的UDAF聚合函数,这里不用group by
        ) as a
    on 1=1  --笛卡尔积

     优化二:

    优化一的本质是减少笛卡尔积处理的数据量,但是因为笛卡尔积是单条处理的,类似orderby的全局问题,在活跃客户量比较大时,大量客户逐条join一条活动处理仍然很慢,优化程度仍然不够。

     

    附:笛卡尔积常用场景

    1.常用于给表的每条记录加上一些通用性质(都是单一取值),如本题中整体活动清单(对所有cust活动清单都是一样的,只有单一取值)就是通用的,也可以用于加一些汇总值,通用时间属性等之类。

    eg:查看每个项目的营业收入,并且每条数据要附上总营收

    select  
         a.proj_name
        ,a.income
        ,b.all_income
        ,b.avg_income
    from tb_proj_income
    inner join (        -- 在这里添加通用属性。一个优化思路:如果上面的主select语句中有很多通用重复计算,也可以采用将其固定下来在inner join的子查询中
        select 
            sum(income) as all_income
            avg(income) as avg_income  --注意这里sum、avg的取值都是单一的
        from tb_proj_income
        ) as b
    
    --因为除聚合函数,其余字段要加group by, select proj_name,sum(income)实现不了

    2.计算留存率等

  • 相关阅读:
    IBM openblockchain学习(五)--consensus源码分析
    Linux内核抢占机制
    IBM openblockchain学习(四)--crypto源码分析
    IBM openblockchain学习(三)--Ledger源码分析
    IBM openblockchain学习(二)--chaincode源码分析
    瞎谈“认知计算”
    IBM openblockchain学习(一)--obc-peer环境搭建
    10G数据不用框架快速去重
    Spark学习笔记(一)--Spark架构
    HDU2255 【模板】KM算法
  • 原文地址:https://www.cnblogs.com/foolangirl/p/14197958.html
Copyright © 2011-2022 走看看