1. 程式人生 > 其它 >離線數倉(九)

離線數倉(九)

9 數倉搭建-ADS

9.1 建表說明

  ADS層不涉及建模,建表根據具體需求而定

9.2 訪客主題

9.2.1 訪客統計

  1.建表語句

drop table if exists ads_visit_stats;
create external table ads_visit_stats(
    `dt` string comment '統計日期',
    `is_new` string comment '新老標識,1:新,0:老',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `channel` string comment 
'渠道', `uv_count` bigint comment '日活(訪問人數)', `duration_sec` bigint comment '頁面停留總時長', `avg_duration_sec` bigint comment '一次會話,頁面停留平均時長,單位為描述', `page_count` bigint comment '頁面總瀏覽數', `avg_page_count` bigint comment '一次會話,頁面平均瀏覽數', `sv_count` bigint comment '會話次數', `bounce_count` bigint comment
'跳出數', `bounce_rate` decimal(16,2) comment '跳出率' ) comment '訪客統計' row format delimited fields terminated by '\t' location '/warehouse/gmall/ads/ads_visit_stats/';

  2.資料裝載

-- 指定spark生成的檔案,自動進行合併
set hive.merge.sparkfiles=true;
-- 256000000 預設合併後的檔案,不超過256M,如果超過256M,自動滾動,產生新的檔案 128M
set hive.merge.size.per.task;
--為了解決小檔案問題,在寫入ads層時,先把歷史資料查詢出來和今天的指標合併,之後覆蓋寫入到ads層表目錄,所有的資料,只有一個檔案 insert overwrite table ads_visit_stats select * from ads_visit_stats union all --求不同的is_new,channal,recent_days 分組下,所有session的指標 select '2021-06-08' dt, --統計日期 is_new, --新老標識,1:新,0:老 recent_days, --最近天數,1:最近1天,7:最近7天,30:最近30天 channel, --渠道 -- 人數(裝置數) 不是 人次,人數應該按照mid_id進行去重統計 count(distinct split(session_id,'-')[0]) uv_count, --日活(訪問人數) sum(duration_sec_per_session) duration_sec, --頁面停留總時長 avg(duration_sec_per_session) avg_duration_sec, --一次會話,頁面停留平均時長,單位為描述 sum(page_count_per_session) page_count, --頁面總瀏覽數 avg(page_count_per_session) avg_page_count, --一次會話,頁面平均瀏覽數 count(*) sv_count, --會話次數 sum(`if`(page_count_per_session = 1,1,0)) bounce_count, --跳出數:指僅有一次訪問行為的會話的數量 cast(sum(`if`(page_count_per_session = 1,1,0)) / count(*) * 100 as DECIMAL(16,2)) bounce_rate --跳出率:跳出數 / 會話總數 * 100 from ( --求不同的is_new,channal,recent_days 分組下,每個session 頁面停留總時長 和 page_count select is_new, --是否首次啟動 channel, --渠道 recent_days, --最近天數 session_id, --sessionId count(*) page_count_per_session, --頁面總瀏覽數 sum(during_time) duration_sec_per_session --頁面停留總時長 from ( -- 求出每次會話的session_id -- 統計日期指統計的資料的日期 select '2021-06-08' dt, is_new, --是否首次啟動 channel, --渠道 mid_id, --裝置id during_time, --持續時間 last_page_id, --上頁型別 page_id, --頁面id ts, --時間 recent_days, --最近天數 concat(mid_id,'-',last_value(`if`(last_page_id is null ,ts,null) ,true) over (partition by mid_id order by ts )) session_id --sessionId from dwd_page_log --側寫 lateral view explode(`array`(1,7,30)) tmp as recent_days -- 要求最近7天和30天的統計指標,要從dwd事實中取資料的範圍,應該在最近30天 where dt > date_sub('2021-06-08',30) --過濾 and dt > date_sub('2021-06-08',recent_days) ) t1 -- 按照is_new,channal,recent_days分組 group by is_new,channel,recent_days,session_id )t2 group by is_new,channel,recent_days;

9.2.2 路徑分析

  1.建表語句

drop table if exists ads_page_path;
create external table ads_page_path(
    `dt` string comment '統計日期',
    --分組的欄位
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    --開窗
    `source` string comment '跳轉起始頁面ID',
    `target` string comment '跳轉終到頁面ID',
    `path_count` bigint comment '跳轉次數'
) comment '頁面瀏覽路徑'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_page_path/'

  2.資料裝載

insert overwrite table ads_page_path
select * from ads_page_path
union all
select  '2021-06-08' dt,
        --求每個session中,從A頁面跳轉到B頁面跳轉了多少次
        recent_days,
        source,
        target,
        count(*)  path_count
from (
    -- 由於產生了閉環,因此需要給一次session訪問的所有的頁面路徑,根據訪問的順序新增id,避免產生閉環
     select recent_days,
            concat(source, '-', rn)     source,
            concat(target, '-', rn + 1) target
     from (
              --求每個session中,根據頁面的訪問順序,生成source和target
              select recent_days,                                                                    --最近天數
                     last_page_id,                                                                   --上頁型別
                     page_id,                                                                        --頁面id
                     page_id                                                                 source, --跳轉起始頁面ID
                     lead(page_id, 1) over (partition by session_id,recent_days order by ts) target, --跳轉終到頁面ID
                     mid_id,                                                                         --裝置id
                     session_id,
                     row_number() over (partition by session_id,recent_days order by ts)     rn
              from (
                       --先求出了每個頁面訪問記錄的session_id
                       select recent_days,  --最近天數
                              last_page_id, --上頁型別
                              page_id,      --頁面id
                              mid_id,       --裝置id
                              ts,           --時間
                              concat(mid_id, '-', last_value(`if`(last_page_id is null, ts, null), true)
                                                             over (partition by mid_id order by ts)) session_id
                       from dwd_page_log
                                --側寫
                                lateral view explode(`array`(1, 7, 30)) tmp as recent_days
                            --全域性過濾
                       where dt > date_sub('2021-06-08', 30)
                         --側寫後過濾
                         and dt > date_sub('2021-06-08', recent_days)
                   ) tmp
          ) tmp1
    )tmp2
group by recent_days,source,target;

9.3 使用者主題

9.3.1 使用者統計

  1.建表語句

drop table if exists ads_user_totalt;
create external table ads_user_totalt(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,0:累積值,1:最近1天,7:最近7天,30:最近30天',
    `new_user_count` bigint comment '新註冊使用者數',
    `new_order_user_count` bigint comment '新增下單使用者數',
    `order_final_amount` decimal(16,2) comment '下單總金額',
    `order_user_count` bigint comment '下單使用者數',
    `no_order_user_count` bigint comment '未下單使用者數(具體指活躍使用者中未下單使用者)'
) comment '使用者統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_total/';

  2.資料裝載

insert overwrite table ads_user_totalt
select *
from ads_user_totalt
union all
select '2021-06-08' dt,
       recent_days,
       sum(`if`(login_date_first > date_sub('2021-06-08',x),1,0)) new_user_count,               --新註冊使用者數
       sum(`if`(order_date_first > date_sub('2021-06-08',x),1,0)) new_order_user_count,         --新增下單使用者數
       sum(order_final_amount) order_final_amount,                                              --下單總金額
       sum(`if`(order_final_amount > 0,1,0)) order_user_count,                                  --下單使用者數
       sum(`if`(login_date_last > date_sub('2021-06-08',x) and order_final_amount = 0, 1,0)) no_order_user_count    --只登陸不下單的使用者數
from
(
    select recent_days,
           user_id,
           login_date_last,     --末次活躍日期
           login_date_first,    --首次活躍日期
           order_date_first,    --首次下單時間
           case recent_days
                when 0 then order_final_amount
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_final_amount,                         --累計最終下單金額
           `if`(recent_days = 0, 65555, recent_days) x      --動態變化:如果是0,表示累計數,否則就是recent_days
    from dwt_user_topic
    lateral view explode(`array`(0,1,7,30)) tmp as recent_days
    where dt = '2021-06-08'
) t1
group by recent_days;

9.3.2 使用者變動統計

  1.建表語句

drop table if exists ads_user_change;
create external table ads_user_change(
    `dt` string comment '統計日期',
    `user_churn_count` bigint comment '流失使用者數',  --最近7天未活躍的使用者=login_date_last <= date_sub(統計日期, 7),也就是說最後一次登入是在7天以前
    `user_back_count` bigint comment '迴流使用者數'   --本週未活躍的老使用者 = 本週活躍的老使用者 與 上週活躍的老使用者 之間的差集
) comment '使用者變動統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_change/';

  2.資料裝載

insert overwrite table ads_user_change
select * from ads_user_change
union all
select '2021-06-08' dt,
       user_churn_count,
       user_back_count
from
(
    select count(*) user_back_count     --迴流使用者數
    from
    (
        --求出本週活躍的老使用者
        select user_id
        from dwt_user_topic
        where dt = '2021-06-08'
        --本週活躍= 最後一次活躍時間 > 7天前的時間
        and login_date_last >= date_sub(next_day('2021-06-08','Monday'),7)
        --老使用者:第一次活躍時間 < 7天前,也就是說7天前活躍過
        and login_date_first < date_sub(next_day('2021-06-08','Monday'),7)
    ) t1
    left join
    (
        --求上週活躍的使用者,注意無法從dwt層求出,dwt層的資料是每日更新,歷史狀態是無法保留的, 只能從dws取上週時間範圍的資料
        select user_id
        from dws_user_action_daycount
        where dt between date_sub(next_day('2021-06-08','Monday'),14) and date_sub(next_day('2021-06-08','Monday'),8)
        --分組去重
        group by user_id
    ) t2 on t1.user_id = t2.user_id
where t2.user_id is null ) t3
join
(
    --求流失使用者:每一條資料代表一個流失的使用者
    select count(*) user_churn_count
    from dwt_user_topic
    where dt = '2021-06-08' and login_date_last <= date_sub('2021-06-08',7)     --最後一次活躍時間小於7天之前
) t4;

9.3.3 使用者行為漏斗分析

  1.建表語句

drop table if exists ads_user_action;
create external table ads_user_action(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `home_count` bigint comment '瀏覽首頁人數',
    `good_detail_count` bigint comment '瀏覽商品詳情頁人數',
    `cart_count` bigint comment '加入購物車人數',
--dwt_user_topic `order_count` bigint comment
'下單人數', `payment_count` bigint comment '支付人數' ) comment '漏斗分析' row format delimited fields terminated by '\t' location '/warehouse/gmall/ads/ads_user_action/';

  2.資料裝載

insert overwrite table ads_user_action
select *
from ads_user_action
union all
select '2021-06-08' dt,
       t5.recent_days,
       home_count,
       good_detail,
       cart_count,
       order_count,
       payment_count
from
(
    select recent_days,
           sum(`if`(page_id = 'home',1,0)) home_count,             --瀏覽首頁人數
           sum(`if`(page_id = 'good_detail',1,0)) good_detail      --瀏覽商品詳情頁人數
    from
    (
        select recent_days,
               user_id,         --使用者id
               page_id          --頁面id
        from dwd_page_log
        --側寫
        lateral view explode(`array`(1,7,30)) tmp as recent_days
        -- 截至到6-8日,最近30天的頁面訪問記錄,全域性過濾
        where dt > date_sub('2021-06-08',30)
        --側寫後的過濾
        and dt > date_sub('2021-06-08',recent_days)
        --只要 首頁和商品詳情頁的瀏覽記錄
        and page_id in ('home','good_detail')
        --要求必須有User的資訊
        and user_id is not null
        --在1,7,30中,每個user訪問每個頁面(home,good_detail)多少次
        group by recent_days,user_id,page_id
    ) t4
    group by recent_days
) t5
join
(
    -- 如果將dwt層的資料,複製3份,直接側寫,無需過濾,
    -- 如果將dwd層的資料複製3份,側寫後需要過濾
    select recent_days,
           sum(`if`(cart_count > 0,1,0)) cart_count,        --加入購物車人數
           sum(`if`(order_count > 0,1,0)) order_count,      --下單人數
           sum(`if`(payment_count > 0,1,0)) payment_count   --支付人數
    from
    (
        select  recent_days,
                case recent_days
                    when 1 then cart_last_1d_count
                    when 7 then cart_last_7d_count
                    when 30 then cart_last_30d_count
                end cart_count,      --加入購物車人數
                case recent_days
                    when 1 then order_last_1d_count
                    when 7 then order_last_7d_count
                    when 30 then order_last_30d_count
                end order_count,     --下單人數
                case recent_days
                    when 1 then payment_last_1d_count
                    when 7 then payment_last_7d_count
                    when 30 then payment_last_30d_count
                end payment_count     --支付人數
        from dwt_user_topic
        lateral view explode(`array`(1,7,30)) tmp as recent_days
        where dt = '2021-06-08'
    ) t1
    group by recent_days
) t6 on t5.recent_days = t6.recent_days;

9.3.4 使用者留存率

  1.建表語句

drop table if exists ads_user_retention;
create external table ads_user_retention(
    `dt` string comment '統計日期',
    `create_date` string comment '使用者新增日期',       --使用者新增的日期 + 留存天數 = 留存N天使用者活躍的日期
    `retention_day` bigint comment '截至當前日期留存天數',
    `retention_count` bigint comment '留存使用者數量',    --某天新增的新使用者,在距離新增日期N天后,依然活躍,則稱為N天的留存使用者
    `new_user_count` bigint comment '新增使用者數量',
    `retention_rate` decimal(16,2) comment '留存率'    --N留存使用者 / N天新增使用者
) comment '使用者留存率'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_retention/';

  2.資料裝載

    1)1日留存

insert overwrite table ads_user_retention
select *
from ads_user_retention
union all
select '2021-06-08' dt,
date_sub('2021-06-08',1) create_date, --使用者新增日期
1 retention_day, --截至當前日期留存天數
-- 留存使用者數量:6-7日新增的這批人,6-8日依舊訪問的有多少人
sum(`if`(login_date_first = date_sub('2021-06-08',1) and login_date_last = '2021-06-08', 1,0)) retention_count,
--新增使用者數量:6-7日新增多少人
sum(`if`(login_date_first = date_sub('2021-06-08',1) ,1,0)) new_user_count,
--留存率 = 1日留存使用者數量 / 1日新增使用者數量
cast(sum(`if`(login_date_first = date_sub('2021-06-08',1) and login_date_last = '2021-06-08', 1,0)) /
sum(`if`(login_date_first = date_sub('2021-06-08',1) ,1,0)) * 100 as decimal(16,2)) retention_rate
from dwt_user_topic
-- 取最新的全體使用者的資訊
where dt = '2021-06-08';

    2)7日留存

insert overwrite table ads_user_retention
select *
from ads_user_retention
union all
-- 求最近7日留存
select  '2021-06-08'  dt,
        login_date_first create_date,                                   --使用者新增日期
        datediff('2021-06-08',login_date_first) retention_day,          --截至當前日期留存天數
        sum(`if`(login_date_last='2021-06-08',1,0)) retention_count,    --留存使用者數量:7天之內活躍,現在依然活躍
        count(*) new_user_count,                                        --新增使用者數量
        --留存率
        cast( sum(`if`(login_date_last='2021-06-08',1,0)) / count(*) * 100 as decimal(16,2)) retention_rate
from dwt_user_topic
-- 取最新的全體使用者的資訊
where dt ='2021-06-08'
-- 從全部使用者中過濾出  2021-06-01 ~ 2021-06-07 日新增的使用者
and login_date_first >= date_sub('2021-06-08',7) and login_date_first < '2021-06-08'
--按照使用者新增的日期分組,求每個新增日期,新增了多少人
group by login_date_first;

9.4 商品主題

9.4.1 商品統計

  1.建表語句

drop table if exists ads_order_spu_stats;
create external table ads_order_spu_stats(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `spu_id` string comment '商品ID',
    `spu_name` string comment '商品名稱',
    `tm_id` string comment '品牌ID',
    `tm_name` string comment '品牌名稱',
    `category3_id` string comment '三級品類ID',
    `category3_name` string comment '三級品類名稱',
    `category2_id` string comment '二級品類ID',
    `category2_name` string comment '二級品類名稱',
    `category1_id` string comment '一級品類ID',
    `category1_name` string comment '一級品類名稱',
    `order_count` bigint comment '訂單數',
    `order_amount` decimal(16,2) comment '訂單金額'
) comment '商品銷售統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_order_spu_stats/';

  2.資料裝載

insert overwrite table ads_order_spu_stats
select *
from ads_order_spu_stats
union all
select '2021-06-08' dt,
       recent_days,
       spu_id,
       spu_name,
       tm_id,
       tm_name,
       category3_id,
       category3_name,
       category2_id,
       category2_name,
       category1_id,
       category1_name,
       sum(order_count) order_count,
       sum(order_amount) order_amount
from
(
    -- 取要統計的指標
    select  sku_id,
            recent_days,
            -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
            case recent_days
                when 1 then order_last_1d_count
                when 7 then order_last_7d_count
                when 30 then order_last_30d_count
            end order_count,        --訂單數
            case recent_days
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_amount        --訂單金額
    from dwt_sku_topic
    --側寫
    lateral view explode(`array`(1,7,30)) tmp as recent_days
    where dt = '2021-06-08'
) t1
left join
(
    -- 查詢需要的維度資訊
    select id,              --skuId
           spu_id,          --商品ID
           tm_id,           --品牌ID
           tm_name,         --品牌名稱
           category3_id,    --三級品類ID
           category3_name,  --三級品類名稱
           category2_id,    --二級品類ID
           category2_name,  --二級品類名稱
           category1_id,    --一級品類ID
           category1_name,  --一級品類名稱
           spu_name         --商品名稱
    from dim_sku_info
    where dt = '2021-06-08'
) t2 on t1.sku_id = t2.id
--spu_id和其他的維度欄位是1對1的關係,所以可以直接附加在group by sku_id後
group by   recent_days,
           spu_id,
           spu_name,
           tm_id,
           tm_name,
           category3_id,
           category3_name,
           category2_id,
           category2_name,
           category1_id,
           category1_name;

9.4.2 品牌復購率

  1.建表語句

drop table if exists ads_repeat_purchase;
create external table ads_repeat_purchase(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `tm_id` string comment '品牌ID',
    `tm_name` string comment '品牌名稱',
    `order_repeat_rate` decimal(16,2) comment '復購率'
) comment '品牌復購率'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_repeat_purchase/';

  2.資料裝載

insert overwrite table ads_repeat_purchase
select * from ads_repeat_purchase
union all
select  '2021-06-08' dt,
        recent_days,
        tm_id,
        tm_name,
        -- 根據每個user購買過的單數,判斷是購買過多次的人還是購買過的人
        -- 求購買過多次的人數
        cast(sum(if(order_times > 1 ,1,0 )) / count(*) * 100 as decimal(16,2)) order_repeat_rate
from
(
    select  recent_days,user_id,tm_id,tm_name,
            -- 購買過多少單,下單過多少次
            --關聯商品維度表,將sku_id切換為tm_id
            count(distinct  order_id) order_times
    from
    (
        --哪些使用者購買了什麼商品的所有的記錄
        select user_id,
               sku_id,
               order_id,
               recent_days
        from dwd_order_detail
        lateral view explode(`array`(1,7,30)) tmp as recent_days
        -- 要取6-8號及之前的資料,至少要取30天的資料,全域性過濾
        where dt > date_sub('2021-06-08',30) and dt > date_sub('2021-06-08',recent_days)
    ) t1
    left join
    (
        --求維度資訊
        select id,
               tm_id,
               tm_name
        from dim_sku_info
        where dt = '2021-06-08'
    ) t2 on t1.sku_id = t2.id
--由於要統計一個人購買過1次(下單次數,單)還是多次,所以先求每個人購買每個品牌的次數
group by recent_days,user_id,tm_id,tm_name) t3
group by recent_days,tm_id,tm_name;

9.5 訂單主題

9.5.1 訂單統計

  1.建表語句

drop table if exists ads_order_total;
create external table ads_order_total(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `order_count` bigint comment '訂單數',
    `order_amount` decimal(16,2) comment '訂單金額',
    `order_user_count` bigint comment '下單人數'
) comment '訂單統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_order_total/';

  2.資料裝載

insert overwrite table ads_order_total
select *
from ads_order_total
union all
select '2021-06-08' dt,
       recent_days,
       sum(order_count) order_count,
       sum(order_amount) order_amount,
       sum(`if`(order_amount > 0, 1,0)) order_user_count
from
(
    select user_id,
           recent_days,
           -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
           case recent_days
                when 1 then order_last_1d_count
                when 7 then order_last_7d_count
                when 30 then order_last_30d_count
            end order_count,        --訂單數
           case recent_days
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_amount        --訂單金額
    from dwt_user_topic
    lateral view explode(`array`(1,7,30)) tmp as recent_days
    --儲存的是截至到6-8日,累積的所有使用者的行為記錄
    where dt = '2021-06-08'
) t1
group by recent_days;

9.5.2 各地區訂單統計

  1.建表語句

drop table if exists ads_order_by_province;
create external table ads_order_by_province(
    `dt` string comment '統計日期',
    `recent_days` bigint comment '最近天數,1:最近1天,7:最近7天,30:最近30天',
    `province_id` string comment '省份id',
    `province_name` string comment '省份名稱',
    `area_code` string comment '地區編碼',
    `iso_code` string comment '國際標準地區編碼',
    `iso_code_3166_2` string comment '國際標準地區編碼',
    `order_count` bigint comment '訂單數',
    `order_amount` decimal(16,2) comment '訂單金額'
) comment '各地區訂單統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_order_by_province/';

  2.資料裝載

insert overwrite table ads_order_by_province
select *
from ads_order_by_province
union all
select '2021-06-08' dt,
       recent_days,
       province_id,
       province_name,
       area_code,
       t2.iso_code iso_code,
       t2.iso_3166_2 iso_code_3166_2,
       order_count,
       order_amount
from
(
    --按照省份id和recent_days分組
    select province_id,
           recent_days,
           sum(order_count) order_count,    --訂單數
           sum(order_amount) order_amount   --訂單金額
    from
    (
        --按地區id、recent_days分組,求訂單數和訂單金額
        select province_id,
               recent_days,
               -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
               case recent_days
                    when 1 then order_last_1d_count
                    when 7 then order_last_7d_count
                    when 30 then order_last_30d_count
                end order_count,        --訂單數
               case recent_days
                    when 1 then order_last_1d_final_amount
                    when 7 then order_last_7d_final_amount
                    when 30 then order_last_30d_final_amount
                end order_amount       --訂單金額
        from dwt_area_topic
        lateral view explode(`array`(1,7,30)) tmp as recent_days
        where dt = '2021-06-08'
    ) tmp
    group by recent_days, province_id
) t1
join
(
    --求維度資訊
    select id,
           province_name,
           area_code,
           iso_3166_2,
           iso_code
    from dim_base_province
) t2 on t1.province_id = t2.id;

9.6 優惠券主題

9.6.1 優惠券統計

  1.建表語句

drop table if exists ads_coupon_stats;
create external table ads_coupon_stats(
    `dt` string comment '統計日期',
    `coupon_id` string comment '優惠券ID',
    `coupon_name` string comment '優惠券名稱',
    `start_date` string comment '釋出日期',
    `rule_name` string comment '優惠規則',
    `get_count` bigint comment '領取次數',
    `order_count` bigint comment '使用(下單)次數',
    `expire_count` bigint comment '過期次數',
    `order_original_amount` decimal(16,2) comment '使用優惠券訂單原始金額',
    `order_final_amount` decimal(16,2) comment '使用優惠券訂單最終金額',
    `reduce_amount` decimal(16,2) comment '優惠金額',
    `reduce_rate` decimal(16,2) comment '補貼率',
    `spu_comment` string comment '商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%',
    `tm_comment` string comment '品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%'
) comment '商品銷售統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_coupon_stats/';

  2.建立UDAF函式,命名為top3,詳細資訊:https://www.cnblogs.com/LzMingYueShanPao/p/14938683.html

    說明:spu_commenttm_comment欄位使用SQL實現較為複雜,所以採用自定義UDAF函式實現

  3.資料裝載

insert overwrite table ads_coupon_stats
select * from ads_coupon_stats
union  all
select '2021-06-08' dt,
       t1.coupon_id,
       coupon_name,
       start_date,
       rule_name,
       nvl(get_count,0),
       nvl(order_count,0),
       nvl(expire_count,0),
       nvl(order_original_amount,0.0),
       nvl(order_final_amount,0.0),
       nvl(reduce_amount,0.0),
       nvl(reduce_rate,0),
       spu_comment,
       tm_comment
from
(
    select id coupon_id,        --優惠券ID
           coupon_name,         --優惠券名稱
           date_format(start_time,'yyyy-MM-dd') start_date, --釋出日期
           -- 需要根據coupon_type,將優惠券的優惠規則拼接
           case coupon_type
                when '3201' then  concat('滿' , condition_amount ,'減' , benefit_amount ,'元')
                when '3202' then  concat('滿' , condition_num ,'打' , benefit_discount ,'折')
                when '3203' then  concat('立減' , condition_amount ,'元' )
            end rule_name       --優惠規則
    from dim_coupon_info
    where dt = '2021-06-08'
    --在30天內有效的優惠券
    and date_format(nvl(expire_time,'9999-99-99'),'yyyy-MM-dd') > date_sub('2021-06-08',30)
) t1
left join
(
    select coupon_id,
           get_count,               --領取次數
           order_count,             --使用(下單)次數
           expire_count,            --過期次數
           order_original_amount,   --使用優惠券訂單原始金額
           order_final_amount,      --使用優惠券訂單最終金額
           payment_reduce_amount reduce_amount,     --優惠金額
           cast(payment_reduce_amount / order_original_amount * 100 as decimal(16,2)) reduce_rate   --補貼率
    from dwt_coupon_topic
    where dt = '2021-06-08'
) t2 on t1.coupon_id = t2.coupon_id
left join
(
    select coupon_id,
           top3(tm_name)  tm_comment,
           top3(spu_name) spu_comment
    from
     (
         -- 先求使用不同種類優惠券的下單購買的訂單的品牌資訊
         select sku_id,
                coupon_id
         from dwd_order_detail
              --取最近30天的下單資訊,全域性過濾
         where dt > date_sub('2021-06-08', 30)
           -- 只求使用了優惠券的訂單購買詳請
           and coupon_id is not null
     ) t3
    left join
    (
        select id,          --sku_id
               tm_name,     --品牌名稱
               spu_name     --spu名稱
        from dim_sku_info
        where dt = '2021-06-08'
    ) t4 on t3.sku_id = t4.id
    group by coupon_id
) t5
on t1.coupon_id = t5.coupon_id;

9.7 活動主題

9.7.1 活動統計

  1.建表語句

drop table if exists ads_activity_stats;
create external table ads_activity_stats(
    `dt` string comment '統計日期',
    `activity_id` string comment '活動ID',
    `activity_name` string comment '活動名稱',
    `start_date` string comment '活動開始日期',
    `order_count` bigint comment '參與活動訂單數',
    `order_original_amount` decimal(16,2) comment '參與活動訂單原始金額',
    `order_final_amount` decimal(16,2) comment '參與活動訂單最終金額',
    `reduce_amount` decimal(16,2) comment '優惠金額',
    `reduce_rate` decimal(16,2) comment '補貼率',
    `rule_comment` string comment '訂單規則佔比,按訂單數統計,要求結果形式如下:滿100減10:19.5%,滿200減30:80.5%',
    `spu_comment` string comment '商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%',
    `tm_comment` string comment '品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%'
) comment '商品銷售統計'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_activity_stats/';

  2.資料裝載

insert overwrite table ads_activity_stats
select * from ads_activity_stats
union  all
select '2021-06-08' dt,
       t1.activity_id,                      --活動ID
       activity_name,                       --活動名稱
       start_date,                          --活動開始日期
       nvl(order_count,0),                 --參與活動訂單數
       nvl(order_original_amount,0.0),     --參與活動訂單原始金額
       nvl(order_final_amount,0.0),        --參與活動訂單最終金額
       nvl(reduce_amount,0.0),             --優惠金額
       nvl(reduce_rate,0),                 --補貼率
       rule_comment,    --訂單規則佔比,按訂單數統計,要求結果形式如下:滿100減10:19.5%,滿200減30:80.5%
       spu_comment,     --商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%
       tm_comment       --品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%
from
(
    --統計最新30天,所有在有效期範圍 的優惠券的維度資訊
    select activity_id,                                             --活動ID
           max(activity_name) activity_name,                        --活動名稱
           min(date_format(start_time,'yyyy-MM-dd')) start_date     --活動開始日期
     -- 一個活動規則是1條,在聚合時,依然要按照活動規則聚合,之後再關聯時,使用活動關聯
    from dim_activity_rule_info
    where dt = '2021-06-08'
    --在30天內有效的活動
    --and date_format(nvl(end_time,'9999-99-99'),'yyyy-MM-dd') > date_sub('2021-06-08',30)
    group by activity_id
) t1
left join
(
    select activity_id,
           sum(order_count) order_count,                        --參與活動訂單數
           sum(order_original_amount) order_original_amount,    --參與活動訂單原始金額
           sum(order_final_amount) order_final_amount,          --參與活動訂單最終金額
           sum(payment_reduce_amount) reduce_amount,            --優惠金額
           --nvl(cast(sum(payment_reduce_amount) / sum(order_original_amount) * 100 as decimal(16,2)),0) reduce_rate     --補貼率
           case sum(payment_reduce_amount)
               when 0 then 0.0
               else nvl(cast(sum(payment_reduce_amount) / sum(payment_reduce_amount) * 100 as decimal(16,2)),0.0)
            end reduce_rate     --補貼率
    from dwt_activity_topic
    where dt = '2021-06-08'
    group by activity_id
) t2 on t1.activity_id = t2.activity_id
left join
(
    select activity_id,
           top3(rule_name) rule_comment,    --訂單規則佔比,按訂單數統計,要求結果形式如下:滿100減10:19.5%,滿200減30:80.5%
           top3(tm_name) tm_comment,        --品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%
           top3(spu_name) spu_comment       --商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%
    from
    (
        -- 先求使用不同種類優惠券的下單購買的訂單的品牌資訊
        select sku_id,activity_rule_id,activity_id
        from dwd_order_detail
        --取最近30天的下單資訊,全域性過濾
        where dt > date_sub('2021-06-08',30)
        and activity_rule_id is not null
    ) t3
    left join
    (
        select id,
               tm_name,     --品牌名稱
               spu_name     --spu名稱
        from dim_sku_info
        where dt = '2021-06-08'
    ) t4 on t3.sku_id = t4.id
    left join
    (
        select activity_rule_id,
               case activity_type
                    when '3101' then  concat('滿' , condition_amount ,'減' , benefit_amount ,'元')
                    when '3102' then  concat('滿' , condition_num ,'打' , benefit_discount ,'折')
                    when '3103' then  concat('立減' , condition_amount ,'元' )
               end rule_name    --規則名稱
        from dim_activity_rule_info
        where dt = '2021-06-08'
    ) t5 on t3.activity_rule_id = t5.activity_rule_id
    group by t3.activity_id
) t6 on t1.activity_id = t6.activity_id;

9.9 ADS業務資料匯入指令碼

  1)編寫指令碼

    (1)在/home/atguigu/bin目錄下建立指令碼dwt_to_ads.sh

vim dwt_to_ads.sh
#!/bin/bash

APP=gmall
# 如果是輸入的日期按照取輸入日期;如果沒輸入日期取當前時間的前一天
if [ -n "$2" ] ;then
   do_date=$2
else 
   do_date= date -d "-1 day" +%F 
fi

ads_visit_stats="
-- 指定spark生成的檔案,自動進行合併
set hive.merge.sparkfiles=true;
-- 256000000 預設合併後的檔案,不超過256M,如果超過256M,自動滾動,產生新的檔案 128M
set hive.merge.size.per.task;
--為了解決小檔案問題,在寫入ads層時,先把歷史資料查詢出來和今天的指標合併,之後覆蓋寫入到ads層表目錄,所有的資料,只有一個檔案
insert overwrite table ${APP}.ads_visit_stats
select *
from ${APP}.ads_visit_stats
union all
--求不同的is_new,channal,recent_days 分組下,所有session的指標
select '$do_date' dt,             --統計日期
       is_new,                      --新老標識,1:新,0:老
       recent_days,                 --最近天數,1:最近1天,7:最近7天,30:最近30天
       channel,                     --渠道
       -- 人數(裝置數) 不是 人次,人數應該按照mid_id進行去重統計
       count(distinct split(session_id,'-')[0]) uv_count,   --日活(訪問人數)
       sum(duration_sec_per_session) duration_sec,          --頁面停留總時長
       avg(duration_sec_per_session) avg_duration_sec,      --一次會話,頁面停留平均時長,單位為描述
       sum(page_count_per_session) page_count,              --頁面總瀏覽數
       avg(page_count_per_session) avg_page_count,          --一次會話,頁面平均瀏覽數
       count(*) sv_count,                                   --會話次數
       sum(if(page_count_per_session = 1,1,0))  bounce_count,     --跳出數:指僅有一次訪問行為的會話的數量
       cast(sum(if(page_count_per_session = 1,1,0)) / count(*) * 100 as DECIMAL(16,2)) bounce_rate    --跳出率:跳出數 / 會話總數  * 100
from
(
    --求不同的is_new,channal,recent_days 分組下,每個session 頁面停留總時長 和  page_count
    select is_new,                                          --是否首次啟動
           channel,                                         --渠道
           recent_days,                                     --最近天數
           session_id,                                      --sessionId
           count(*) page_count_per_session,                 --頁面總瀏覽數
           sum(during_time)  duration_sec_per_session       --頁面停留總時長
    from
    (
        -- 求出每次會話的session_id
        -- 統計日期指統計的資料的日期
        select  '$do_date' dt,
                is_new,             --是否首次啟動
                channel,            --渠道
                mid_id,             --裝置id
                during_time,        --持續時間
                last_page_id,       --上頁型別
                page_id,            --頁面id
                ts,                 --時間
                recent_days,        --最近天數
                concat(mid_id,'-',last_value(if(last_page_id is null ,ts,null) ,true) over (partition by mid_id order by ts )) session_id  --sessionId
        from ${APP}.dwd_page_log
        --側寫
        lateral view explode(array(1,7,30)) tmp as recent_days
        -- 要求最近7天和30天的統計指標,要從dwd事實中取資料的範圍,應該在最近30天
        where dt > date_sub('$do_date',30)
        --過濾
        and dt > date_sub('$do_date',recent_days)
    ) t1
-- 按照is_new,channal,recent_days分組
group by is_new,channel,recent_days,session_id )t2
group by is_new,channel,recent_days;
"

ads_page_path="
insert overwrite table ${APP}.ads_page_path
select * from ${APP}.ads_page_path
union all
select  '$do_date' dt,
        --求每個session中,從A頁面跳轉到B頁面跳轉了多少次
        recent_days,
        source,
        target,
        count(*)  path_count
from (
    -- 由於產生了閉環,因此需要給一次session訪問的所有的頁面路徑,根據訪問的順序新增id,避免產生閉環
     select recent_days,
            concat(source, '-', rn)     source,
            concat(target, '-', rn + 1) target
     from (
              --求每個session中,根據頁面的訪問順序,生成source和target
              select recent_days,                                                                    --最近天數
                     last_page_id,                                                                   --上頁型別
                     page_id,                                                                        --頁面id
                     page_id                                                                 source, --跳轉起始頁面ID
                     lead(page_id, 1) over (partition by session_id,recent_days order by ts) target, --跳轉終到頁面ID
                     mid_id,                                                                         --裝置id
                     session_id,
                     row_number() over (partition by session_id,recent_days order by ts)     rn
              from (
                       --先求出了每個頁面訪問記錄的session_id
                       select recent_days,  --最近天數
                              last_page_id, --上頁型別
                              page_id,      --頁面id
                              mid_id,       --裝置id
                              ts,           --時間
                              concat(mid_id, '-', last_value(if(last_page_id is null, ts, null), true)
                                                             over (partition by mid_id order by ts)) session_id
                       from ${APP}.dwd_page_log
                                --側寫
                                lateral view explode(array(1, 7, 30)) tmp as recent_days
                            --全域性過濾
                       where dt > date_sub('$do_date', 30)
                         --側寫後過濾
                         and dt > date_sub('$do_date', recent_days)
                   ) tmp
          ) tmp1
    )tmp2
group by recent_days,source,target;
"

ads_user_totalt="
insert overwrite table ${APP}.ads_user_totalt
select *
from ${APP}.ads_user_totalt
union all
select '$do_date' dt,
       recent_days,
       sum(if(login_date_first > date_sub('$do_date',x),1,0)) new_user_count,               --新註冊使用者數
       sum(if(order_date_first > date_sub('$do_date',x),1,0)) new_order_user_count,         --新增下單使用者數
       sum(order_final_amount) order_final_amount,                                              --下單總金額
       sum(if(order_final_amount > 0,1,0)) order_user_count,                                  --下單使用者數
       sum(if(login_date_last > date_sub('$do_date',x) and order_final_amount = 0, 1,0)) no_order_user_count    --只登陸不下單的使用者數
from
(
    select recent_days,
           user_id,
           login_date_last,     --末次活躍日期
           login_date_first,    --首次活躍日期
           order_date_first,    --首次下單時間
           case recent_days
                when 0 then order_final_amount
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_final_amount,                         --累計最終下單金額
           if(recent_days = 0, 65555, recent_days) x      --動態變化:如果是0,表示累計數,否則就是recent_days
    from ${APP}.dwt_user_topic
    lateral view explode(array(0,1,7,30)) tmp as recent_days
    where dt = '$do_date'
) t1
group by recent_days;
"

ads_user_change="
insert overwrite table ${APP}.ads_user_change
select * from ${APP}.ads_user_change
union all
select '$do_date' dt,
       user_churn_count,
       user_back_count
from
(
    select count(*) user_back_count     --迴流使用者數
    from
    (
        --求出本週活躍的老使用者
        select user_id
        from ${APP}.dwt_user_topic
        where dt = '$do_date'
        --本週活躍= 最後一次活躍時間 > 7天前的時間
        and login_date_last >= date_sub(next_day('$do_date','Monday'),7)
        --老使用者:第一次活躍時間 < 7天前,也就是說7天前活躍過
        and login_date_first < date_sub(next_day('$do_date','Monday'),7)
    ) t1
    left join
    (
        --求上週活躍的使用者,注意無法從dwt層求出,dwt層的資料是每日更新,歷史狀態是無法保留的, 只能從dws取上週時間範圍的資料
        select user_id
        from ${APP}.dws_user_action_daycount
        where dt between date_sub(next_day('$do_date','Monday'),14) and date_sub(next_day('$do_date','Monday'),8)
        --分組去重
        group by user_id
    ) t2 on t1.user_id = t2.user_id
where t2.user_id is null ) t3
join
(
    --求流失使用者:每一條資料代表一個流失的使用者
    select count(*) user_churn_count
    from ${APP}.dwt_user_topic
    where dt = '$do_date' and login_date_last <= date_sub('$do_date',7)     --最後一次活躍時間小於7天之前
) t4;
"

ads_user_action="
insert overwrite table ${APP}.ads_user_action
select *
from ${APP}.ads_user_action
union all
select '$do_date' dt,
       t5.recent_days,
       home_count,
       good_detail,
       cart_count,
       order_count,
       payment_count
from
(
    select recent_days,
           sum(if(page_id = 'home',1,0)) home_count,             --瀏覽首頁人數
           sum(if(page_id = 'good_detail',1,0)) good_detail      --瀏覽商品詳情頁人數
    from
    (
        select recent_days,
               user_id,         --使用者id
               page_id          --頁面id
        from ${APP}.dwd_page_log
        --側寫
        lateral view explode(array(1,7,30)) tmp as recent_days
        -- 截至到6-8日,最近30天的頁面訪問記錄,全域性過濾
        where dt > date_sub('$do_date',30)
        --側寫後的過濾
        and dt > date_sub('$do_date',recent_days)
        --只要 首頁和商品詳情頁的瀏覽記錄
        and page_id in ('home','good_detail')
        --要求必須有User的資訊
        and user_id is not null
        --在1,7,30中,每個user訪問每個頁面(home,good_detail)多少次
        group by recent_days,user_id,page_id
    ) t4
    group by recent_days
) t5
join
(
    -- 如果將dwt層的資料,複製3份,直接側寫,無需過濾,
    -- 如果將dwd層的資料複製3份,側寫後需要過濾
    select recent_days,
           sum(if(cart_count > 0,1,0)) cart_count,        --加入購物車人數
           sum(if(order_count > 0,1,0)) order_count,      --下單人數
           sum(if(payment_count > 0,1,0)) payment_count   --支付人數
    from
    (
        select  recent_days,
                case recent_days
                    when 1 then cart_last_1d_count
                    when 7 then cart_last_7d_count
                    when 30 then cart_last_30d_count
                end cart_count,      --加入購物車人數
                case recent_days
                    when 1 then order_last_1d_count
                    when 7 then order_last_7d_count
                    when 30 then order_last_30d_count
                end order_count,     --下單人數
                case recent_days
                    when 1 then payment_last_1d_count
                    when 7 then payment_last_7d_count
                    when 30 then payment_last_30d_count
                end payment_count     --支付人數
        from ${APP}.dwt_user_topic
        lateral view explode(array(1,7,30)) tmp as recent_days
        where dt = '$do_date'
    ) t1
    group by recent_days
) t6 on t5.recent_days = t6.recent_days;
"

ads_user_retention="
insert overwrite table ${APP}.ads_user_retention
select *
from ${APP}.ads_user_retention
union all
-- 求最近7日留存
select  '$do_date'  dt,
        login_date_first create_date,                                   --使用者新增日期
        datediff('$do_date',login_date_first) retention_day,          --截至當前日期留存天數
        sum(if(login_date_last='$do_date',1,0)) retention_count,    --留存使用者數量:7天之內活躍,現在依然活躍
        count(*) new_user_count,                                        --新增使用者數量
        --留存率
        cast( sum(if(login_date_last='$do_date',1,0)) / count(*) * 100 as decimal(16,2)) retention_rate
from ${APP}.dwt_user_topic
-- 取最新的全體使用者的資訊
where dt ='$do_date'
-- 從全部使用者中過濾出  2021-06-01 ~ 2021-06-07 日新增的使用者
and login_date_first >= date_sub('$do_date',7) and login_date_first < '$do_date'
--按照使用者新增的日期分組,求每個新增日期,新增了多少人
group by login_date_first;
"

ads_order_spu_stats="
insert overwrite table ${APP}.ads_order_spu_stats
select *
from ${APP}.ads_order_spu_stats
union all
select '$do_date' dt,
       recent_days,
       spu_id,
       spu_name,
       tm_id,
       tm_name,
       category3_id,
       category3_name,
       category2_id,
       category2_name,
       category1_id,
       category1_name,
       sum(order_count) order_count,
       sum(order_amount) order_amount
from
(
    -- 取要統計的指標
    select  sku_id,
            recent_days,
            -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
            case recent_days
                when 1 then order_last_1d_count
                when 7 then order_last_7d_count
                when 30 then order_last_30d_count
            end order_count,        --訂單數
            case recent_days
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_amount        --訂單金額
    from ${APP}.dwt_sku_topic
    --側寫
    lateral view explode(array(1,7,30)) tmp as recent_days
    where dt = '$do_date'
) t1
left join
(
    -- 查詢需要的維度資訊
    select id,              --skuId
           spu_id,          --商品ID
           tm_id,           --品牌ID
           tm_name,         --品牌名稱
           category3_id,    --三級品類ID
           category3_name,  --三級品類名稱
           category2_id,    --二級品類ID
           category2_name,  --二級品類名稱
           category1_id,    --一級品類ID
           category1_name,  --一級品類名稱
           spu_name         --商品名稱
    from ${APP}.dim_sku_info
    where dt = '$do_date'
) t2 on t1.sku_id = t2.id
--spu_id和其他的維度欄位是1對1的關係,所以可以直接附加在group by sku_id後
group by   recent_days,
           spu_id,
           spu_name,
           tm_id,
           tm_name,
           category3_id,
           category3_name,
           category2_id,
           category2_name,
           category1_id,
           category1_name;
"

ads_repeat_purchase="
insert overwrite table ${APP}.ads_repeat_purchase
select * from ${APP}.ads_repeat_purchase
union all
select  '$do_date' dt,
        recent_days,
        tm_id,
        tm_name,
        -- 根據每個user購買過的單數,判斷是購買過多次的人還是購買過的人
        -- 求購買過多次的人數
        cast(sum(if(order_times > 1 ,1,0 )) / count(*) * 100 as decimal(16,2)) order_repeat_rate
from
(
    select  recent_days,user_id,tm_id,tm_name,
            -- 購買過多少單,下單過多少次
            --關聯商品維度表,將sku_id切換為tm_id
            count(distinct  order_id) order_times
    from
    (
        --哪些使用者購買了什麼商品的所有的記錄
        select user_id,
               sku_id,
               order_id,
               recent_days
        from ${APP}.dwd_order_detail
        lateral view explode(array(1,7,30)) tmp as recent_days
        -- 要取6-8號及之前的資料,至少要取30天的資料,全域性過濾
        where dt > date_sub('$do_date',30) and dt > date_sub('$do_date',recent_days)
    ) t1
    left join
    (
        --求維度資訊
        select id,
               tm_id,
               tm_name
        from ${APP}.dim_sku_info
        where dt = '$do_date'
    ) t2 on t1.sku_id = t2.id
--由於要統計一個人購買過1次(下單次數,單)還是多次,所以先求每個人購買每個品牌的次數
group by recent_days,user_id,tm_id,tm_name) t3
group by recent_days,tm_id,tm_name;
"

ads_order_total="
insert overwrite table ${APP}.ads_order_total
select *
from ${APP}.ads_order_total
union all
select '$do_date' dt,
       recent_days,
       sum(order_count) order_count,
       sum(order_amount) order_amount,
       sum(if(order_amount > 0, 1,0)) order_user_count
from
(
    select user_id,
           recent_days,
           -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
           case recent_days
                when 1 then order_last_1d_count
                when 7 then order_last_7d_count
                when 30 then order_last_30d_count
            end order_count,        --訂單數
           case recent_days
                when 1 then order_last_1d_final_amount
                when 7 then order_last_7d_final_amount
                when 30 then order_last_30d_final_amount
            end order_amount        --訂單金額
    from ${APP}.dwt_user_topic
    lateral view explode(array(1,7,30)) tmp as recent_days
    --儲存的是截至到6-8日,累積的所有使用者的行為記錄
    where dt = '$do_date'
) t1
group by recent_days;
"

ads_order_by_province="
insert overwrite table ${APP}.ads_order_by_province
select *
from ${APP}.ads_order_by_province
union all
select '$do_date' dt,
       recent_days,
       province_id,
       province_name,
       area_code,
       t2.iso_code iso_code,
       t2.iso_3166_2 iso_code_3166_2,
       order_count,
       order_amount
from
(
    --按照省份id和recent_days分組
    select province_id,
           recent_days,
           sum(order_count) order_count,    --訂單數
           sum(order_amount) order_amount   --訂單金額
    from
    (
        --按地區id、recent_days分組,求訂單數和訂單金額
        select province_id,
               recent_days,
               -- 要sum(x),x隨著recent_days進行變化,因此需要判斷recent_days到底是幾
               case recent_days
                    when 1 then order_last_1d_count
                    when 7 then order_last_7d_count
                    when 30 then order_last_30d_count
                end order_count,        --訂單數
               case recent_days
                    when 1 then order_last_1d_final_amount
                    when 7 then order_last_7d_final_amount
                    when 30 then order_last_30d_final_amount
                end order_amount       --訂單金額
        from ${APP}.dwt_area_topic
        lateral view explode(array(1,7,30)) tmp as recent_days
        where dt = '$do_date'
    ) tmp
    group by recent_days, province_id
) t1
join
(
    --求維度資訊
    select id,
           province_name,
           area_code,
           iso_3166_2,
           iso_code
    from ${APP}.dim_base_province
) t2 on t1.province_id = t2.id;
"

ads_coupon_stats="
insert overwrite table ${APP}.ads_coupon_stats
select * from ${APP}.ads_coupon_stats
union  all
select '$do_date' dt,
       t1.coupon_id,
       coupon_name,
       start_date,
       rule_name,
       nvl(get_count,0),
       nvl(order_count,0),
       nvl(expire_count,0),
       nvl(order_original_amount,0.0),
       nvl(order_final_amount,0.0),
       nvl(reduce_amount,0.0),
       nvl(reduce_rate,0),
       spu_comment,
       tm_comment
from
(
    select id coupon_id,        --優惠券ID
           coupon_name,         --優惠券名稱
           date_format(start_time,'yyyy-MM-dd') start_date, --釋出日期
           -- 需要根據coupon_type,將優惠券的優惠規則拼接
           case coupon_type
                when '3201' then  concat('滿' , condition_amount ,'減' , benefit_amount ,'元')
                when '3202' then  concat('滿' , condition_num ,'打' , benefit_discount ,'折')
                when '3203' then  concat('立減' , condition_amount ,'元' )
            end rule_name       --優惠規則
    from ${APP}.dim_coupon_info
    where dt = '$do_date'
    --在30天內有效的優惠券
    and date_format(nvl(expire_time,'9999-99-99'),'yyyy-MM-dd') > date_sub('$do_date',30)
) t1
left join
(
    select coupon_id,
           get_count,               --領取次數
           order_count,             --使用(下單)次數
           expire_count,            --過期次數
           order_original_amount,   --使用優惠券訂單原始金額
           order_final_amount,      --使用優惠券訂單最終金額
           payment_reduce_amount reduce_amount,     --優惠金額
           cast(payment_reduce_amount / order_original_amount * 100 as decimal(16,2)) reduce_rate   --補貼率
    from ${APP}.dwt_coupon_topic
    where dt = '$do_date'
) t2 on t1.coupon_id = t2.coupon_id
left join
(
    select coupon_id,
           ${APP}.top3(tm_name)  tm_comment,
           ${APP}.top3(spu_name) spu_comment
    from
     (
         -- 先求使用不同種類優惠券的下單購買的訂單的品牌資訊
         select sku_id,
                coupon_id
         from ${APP}.dwd_order_detail
              --取最近30天的下單資訊,全域性過濾
         where dt > date_sub('$do_date', 30)
           -- 只求使用了優惠券的訂單購買詳請
           and coupon_id is not null
     ) t3
    left join
    (
        select id,          --sku_id
               tm_name,     --品牌名稱
               spu_name     --spu名稱
        from ${APP}.dim_sku_info
        where dt = '$do_date'
    ) t4 on t3.sku_id = t4.id
    group by coupon_id
) t5
on t1.coupon_id = t5.coupon_id;
"

ads_activity_stats="
insert overwrite table ${APP}.ads_activity_stats
select * from ${APP}.ads_activity_stats
union  all
select '$do_date' dt,
       t1.activity_id,                      --活動ID
       activity_name,                       --活動名稱
       start_date,                          --活動開始日期
       nvl(order_count,0),                 --參與活動訂單數
       nvl(order_original_amount,0.0),     --參與活動訂單原始金額
       nvl(order_final_amount,0.0),        --參與活動訂單最終金額
       nvl(reduce_amount,0.0),             --優惠金額
       nvl(reduce_rate,0),                 --補貼率
       rule_comment,    --訂單規則佔比,按訂單數統計,要求結果形式如下:滿100減10:19.5%,滿200減30:80.5%
       spu_comment,     --商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%
       tm_comment       --品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%
from
(
    --統計最新30天,所有在有效期範圍 的優惠券的維度資訊
    select activity_id,                                             --活動ID
           max(activity_name) activity_name,                        --活動名稱
           min(date_format(start_time,'yyyy-MM-dd')) start_date     --活動開始日期
     -- 一個活動規則是1條,在聚合時,依然要按照活動規則聚合,之後再關聯時,使用活動關聯
    from ${APP}.dim_activity_rule_info
    where dt = '$do_date'
    --在30天內有效的活動
    --and date_format(nvl(end_time,'9999-99-99'),'yyyy-MM-dd') > date_sub('$do_date',30)
    group by activity_id
) t1
left join
(
    select activity_id,
           sum(order_count) order_count,                        --參與活動訂單數
           sum(order_original_amount) order_original_amount,    --參與活動訂單原始金額
           sum(order_final_amount) order_final_amount,          --參與活動訂單最終金額
           sum(payment_reduce_amount) reduce_amount,            --優惠金額
           --nvl(cast(sum(payment_reduce_amount) / sum(order_original_amount) * 100 as decimal(16,2)),0) reduce_rate     --補貼率
           case sum(payment_reduce_amount)
               when 0 then 0.0
               else nvl(cast(sum(payment_reduce_amount) / sum(payment_reduce_amount) * 100 as decimal(16,2)),0.0)
            end reduce_rate     --補貼率
    from ${APP}.dwt_activity_topic
    where dt = '$do_date'
    group by activity_id
) t2 on t1.activity_id = t2.activity_id
left join
(
    select activity_id,
           ${APP}.top3(rule_name) rule_comment,    --訂單規則佔比,按訂單數統計,要求結果形式如下:滿100減10:19.5%,滿200減30:80.5%
           ${APP}.top3(tm_name) tm_comment,        --品牌佔比,按訂單數統計,要求結果形式如下:Apple:30%,Xiaomi:20%,Huawei:30%,其他:20%
           ${APP}.top3(spu_name) spu_comment       --商品佔比,按訂單數統計,要求結果形式如下:iPhone X:30%,xiaomi 10:20%,iPhone 12:30%,其他:20%
    from
    (
        -- 先求使用不同種類優惠券的下單購買的訂單的品牌資訊
        select sku_id,activity_rule_id,activity_id
        from ${APP}.dwd_order_detail
        --取最近30天的下單資訊,全域性過濾
        where dt > date_sub('$do_date',30)
        and activity_rule_id is not null
    ) t3
    left join
    (
        select id,
               tm_name,     --品牌名稱
               spu_name     --spu名稱
        from ${APP}.dim_sku_info
        where dt = '$do_date'
    ) t4 on t3.sku_id = t4.id
    left join
    (
        select activity_rule_id,
               case activity_type
                    when '3101' then  concat('滿' , condition_amount ,'減' , benefit_amount ,'元')
                    when '3102' then  concat('滿' , condition_num ,'打' , benefit_discount ,'折')
                    when '3103' then  concat('立減' , condition_amount ,'元' )
               end rule_name    --規則名稱
        from ${APP}.dim_activity_rule_info
        where dt = '$do_date'
    ) t5 on t3.activity_rule_id = t5.activity_rule_id
    group by t3.activity_id
) t6 on t1.activity_id = t6.activity_id;
"

case $1 in
    "ads_visit_stats" )
        hive -e "$ads_visit_stats"
    ;;
    "ads_page_path" )
        hive -e "$ads_page_path"
    ;;
    "ads_user_totalt" )
        hive -e "$ads_user_totalt"
    ;;
    "ads_user_change" )
        hive -e "$ads_user_change"
    ;;
    "ads_user_action" )
        hive -e "$ads_user_action"
    ;;
    "ads_user_retention" )
        hive -e "$ads_user_retention"
    ;;
    "ads_order_spu_stats" )
        hive -e "$ads_order_spu_stats"
    ;;
    "ads_repeat_purchase" )
        hive -e "$ads_repeat_purchase"
    ;;
    "ads_order_total" )
        hive -e "$ads_order_total"
    ;;
    "ads_order_by_province" )
        hive -e "$ads_order_by_province"
    ;;
    "ads_coupon_stats" )
        hive -e "$ads_coupon_stats"
    ;;
    "ads_activity_stats" )
        hive -e "$ads_activity_stats"
    ;;
    "all" )
        hive -e "$ads_visit_stats$ads_page_path$ads_user_totalt$ads_user_change$ads_user_action$ads_user_retention$ads_order_spu_stats$ads_repeat_purchase$ads_order_total$ads_order_by_province$ads_coupon_stats$ads_activity_stats"
    ;;
esac

    (2)增加指令碼執行許可權

chmod 777 dwt_to_ads.sh

  2)指令碼使用

    (1)執行指令碼

dwt_to_ads.sh all 2021-06-08    

    (2)檢視資料是否匯入