Просмотр исходного кода

feat: 添加尾号实验、AB分ab对比、洞察SQL、报表及table_gen测试

- 尾号实验: base/base_v1/base_v2 (str校准 & ros天级更新)
- AB效果: 分ab对比SQL+JSON配置、含多跳v2
- 洞察: click top_from_mid、活跃表概况、来源/level_channel/内外部分布
- 报表: 推荐分发报表SQL+JSON
- table_gen: 活跃日志表、测试SQL、tmp笔记

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
yangxiaohui 3 недель назад
Родитель
Сommit
fb57435447
25 измененных файлов с 4756 добавлено и 0 удалено
  1. 421 0
      table_gen/ loghubods.ods_user_active_log_info_day.sql
  2. 722 0
      table_gen/de.sql
  3. 194 0
      table_gen/test_1.sql
  4. 300 0
      table_gen/test_2.sql
  5. 601 0
      table_gen/test_3.sql
  6. 632 0
      table_gen/test_4.sql
  7. 118 0
      table_gen/tmp.md
  8. 139 0
      tasks/00_AB效果/02_推荐AB天级效果_对比对照组_ab.sql
  9. 6 0
      tasks/00_AB效果/02_推荐AB天级效果_对比对照组_分ab.json
  10. 140 0
      tasks/00_AB效果/02_推荐AB天级效果_对比对照组_分ab.sql
  11. 195 0
      tasks/00_AB效果/05_推荐AB天级效果_对比对照组_含多跳_v2.sql
  12. 7 0
      tasks/00_尾号实验/base.json
  13. 123 0
      tasks/00_尾号实验/base.sql
  14. 7 0
      tasks/00_尾号实验/base_v1.json
  15. 122 0
      tasks/00_尾号实验/base_v1.sql
  16. 7 0
      tasks/00_尾号实验/base_v2.json
  17. 128 0
      tasks/00_尾号实验/base_v2.sql
  18. 28 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/05_click_top_from_mid.sql
  19. 29 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/06_活跃表概况.sql
  20. 23 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/07_click_来源分布.sql
  21. 25 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/08_click_level_channel分布.sql
  22. 49 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/09_click_内外部_首层分布.sql
  23. 54 0
      tasks/00_表的洞察/loghubods.user_share_log/00_洞察/10_click_top_from_mid_排除外部首层.sql
  24. 8 0
      tasks/报表/01_推荐分发报表.json
  25. 678 0
      tasks/报表/01_推荐分发报表.sql

+ 421 - 0
table_gen/ loghubods.ods_user_active_log_info_day.sql

@@ -0,0 +1,421 @@
+--odps sql 
+
+
+--********************************************************************--
+--author:李晓阳
+--create time:2025-07-30 11:36:56
+--desc mid区分渠道承接和日常的明细数据表 (优化上线)
+--********************************************************************--
+CREATE TABLE IF NOT EXISTS loghubods.ods_user_active_log_info_day
+(
+    apptype             STRING COMMENT '应用类型'
+    ,loginuid           STRING COMMENT '用户id'
+    ,opengid            STRING COMMENT '群id'
+    ,type               STRING COMMENT '群类型'
+    ,sencetype          STRING COMMENT '群类型_编码'
+    ,hotsencetype       STRING COMMENT '热启动群类型_编码'
+    ,machinecode        STRING COMMENT '设备唯一标识'
+    ,subsessionid       STRING COMMENT '子会话ID'
+    ,sessionid          STRING COMMENT '会话ID'
+    ,rootsourceid       STRING COMMENT '根来源ID'
+    ,rootsessionid      STRING COMMENT '根会话ID'
+    ,layer              BIGINT COMMENT '用户分享层级'
+    ,channel            STRING COMMENT '渠道名称'
+    ,channel_shortname  STRING COMMENT '渠道简称'
+    ,push_type          STRING COMMENT '推送类型(承接/日常/未知)'
+    ,sub_channel        STRING COMMENT '子渠道标识'
+    ,channel_type       STRING COMMENT '渠道类型分类'
+    ,channel_type_frist STRING COMMENT '渠道类型前缀'
+    ,channel_id         BIGINT COMMENT '渠道类型ID'
+    ,level_type         STRING COMMENT '外部首层、非外部首层'
+    ,user_share_depth   BIGINT COMMENT '分享层级'
+    ,browse_time STRING COMMENT '访问时间'
+
+)
+PARTITIONED BY 
+(
+    dt                  STRING COMMENT '数据日期'
+)
+STORED AS ALIORC
+TBLPROPERTIES ('columnar.nested.type' = 'true','comment' = 'mid区分渠道承接和日常的明细数据表')
+;
+--ALTER TABLE loghubods.ods_user_active_log_info_day ADD COLUMNS (channel_type_okr string )
+--ALTER TABLE loghubods.ods_user_active_log_info_day ADD COLUMNS (browse_time string COMMENT '访问时间');
+--ALTER TABLE loghubods.ods_user_active_log_info_day ADD COLUMNS (real_user_share_depth string --COMMENT '真实层级');
+--ALTER TABLE loghubods.ods_user_active_log_info_day ADD COLUMNS (clienttimestamp string );
+INSERT OVERWRITE TABLE loghubods.ods_user_active_log_info_day PARTITION (dt = '${day}')
+WITH -- 1. 基础用户活跃日志CTE:解析JSON字段,过滤公共条件
+base_useractive AS 
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,subsessionid
+            ,sessionid
+            ,businesstype
+            ,GET_JSON_OBJECT(extparams,'$.rootSourceId') AS root_source_id
+            ,GET_JSON_OBJECT(extparams,'$.rootSessionId') AS root_session_id
+            ,GET_JSON_OBJECT(extparams,'$.userShareDepth') AS user_share_depth
+            ,extparams
+            ,loginuid
+            ,opengid
+            ,CASE   WHEN opengid = '-1' THEN '单聊'
+                    WHEN opengid = '-2' THEN '获取失败'
+                    WHEN LENGTH(opengid) > 4 THEN '群聊'
+            END AS type -- ,pagesource
+            ,senceType AS sencetype
+            ,GET_JSON_OBJECT(extParams,'$.hotSenceType') AS hotsencetype
+            ,from_unixtime(cast(clienttimestamp as BIGINT )/1000) browse_time
+            ,clienttimestamp
+    FROM    loghubods.useractive_log
+    WHERE   dt = '${day}'
+    AND     businesstype = 'path'
+) -- 2. 公众号买号分组表
+,gzh_buy_group AS 
+(
+    SELECT  root_source_id AS gzh_buy_root
+    FROM    loghubods.changwen_rootsourceid_group
+    WHERE   dt = MAX_PT('loghubods.changwen_rootsourceid_group')
+    AND     group_name = '公众号买号'
+) -- 3. 服务号信息表(用于服务号代运营场景)
+,service_account AS 
+(
+    SELECT  gzh.gh_id
+            ,account.channel
+            ,CASE   WHEN gzh.type = 0 THEN '公众号'
+                    ELSE '服务号'
+            END AS account_type
+    FROM    loghubods.content_platform_account account
+    LEFT JOIN loghubods.content_platform_gzh_account gzh
+    ON      account.id = gzh.create_account_id
+    WHERE   gzh.type != 0 -- 仅保留服务号
+    GROUP BY gzh.gh_id
+             ,account.channel
+             ,CASE   WHEN gzh.type = 0 THEN '公众号'
+                     ELSE '服务号'
+             END
+) -- 4. 长文数据与分组关联表
+,long_articles_info AS 
+(
+    SELECT  a.rootsourceid
+            ,a.ghid
+            ,c.group_source_name
+            ,a.push_type
+    FROM    loghubods.long_articles_root_source_id a
+    LEFT JOIN loghubods.publish_account b
+    ON      a.ghid = b.gh_id
+    LEFT JOIN loghubods.wx_statistics_group_source_account c
+    ON      b.id = c.account_id
+    WHERE   a.dt = MAX_PT('loghubods.long_articles_root_source_id')
+    GROUP BY a.rootsourceid
+             ,a.ghid
+             ,c.group_source_name
+             ,a.push_type
+) -- 5. 腾讯投放记录表
+,ad_put_flow_tencent AS 
+(
+    SELECT  root_source_id
+            ,put_carrier_id
+            ,put_type_one
+            ,put_type_two
+            ,channel
+    FROM    loghubods.ad_put_flow_record_tencent_day
+    WHERE   dt = '${day}'
+    GROUP BY root_source_id
+             ,put_carrier_id
+             ,put_type_one
+             ,put_type_two
+             ,channel
+) -- 主查询:通过CASE WHEN和LEFT JOIN实现所有渠道类型的统一处理
+SELECT  b.apptype
+        ,b.loginuid
+        ,b.opengid
+        ,b.type
+        ,b.sencetype
+        ,b.hotsencetype
+        ,b.machinecode
+        ,b.subsessionid
+        ,b.sessionid
+        ,b.root_source_id AS rootsourceid
+        ,b.root_session_id AS rootsessionid -- 计算层级layer
+        ,CASE   WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t9.channel REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss' --AND t9.layer_type ='特殊首层' 
+                THEN IF(CAST(b.user_share_depth AS INT) <= 1,1,2)
+                ELSE IF(CAST(b.user_share_depth AS INT) = 0,1,2)
+        END AS layer -- 计算渠道名称、简称
+        ,CASE
+                 -- 公众号即时回复
+                   WHEN b.root_source_id REGEXP 'dyyjs_'
+                    AND SUBSTR(b.root_source_id,7,4) = 'null'
+                    AND t3.ghid_list = 'gh_580589404a08' THEN '浩讯'
+                WHEN b.root_source_id REGEXP 'dyyjs_'
+                    AND SUBSTR(b.root_source_id,7,4) = 'null'
+                    AND t3.ghid_list = 'gh_505269831752' THEN '恒创'
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN t4.company -- 企微外部合作
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' THEN SPLIT_PART(b.root_source_id,'_',2) -- 服务号代运营
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN COALESCE(s.channel,'') -- 公众号买号/长文
+                WHEN b.root_source_id REGEXP 'longArticles_' THEN COALESCE(l.group_source_name,'') -- 其他渠道
+                ELSE ''
+        END AS channel -- 渠道简称(逻辑与channel一致,仅部分场景有简写)
+        ,CASE   WHEN b.root_source_id REGEXP 'dyyjs_'
+                    AND SUBSTR(b.root_source_id,7,4) = 'null'
+                    AND t3.ghid_list = 'gh_580589404a08' THEN 'hx'
+                WHEN b.root_source_id REGEXP 'dyyjs_'
+                    AND SUBSTR(b.root_source_id,7,4) = 'null'
+                    AND t3.ghid_list = 'gh_505269831752' THEN 'hc'
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN t4.company_code
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' THEN SPLIT_PART(b.root_source_id,'_',2)
+                ELSE ''
+        END AS channel_shortname -- 推送类型
+        ,CASE
+                 -- 公众号/服务号投流、企微投流:从长文数据或投放记录获取
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh|fwhtouliu_|touliu_tencentqw_|WeCom_|daitou_tencentgzh|DaiTou_gh' THEN COALESCE(t5.push_type,'未知') -- 公众号即时回复、小程序投流:固定为承接
+                WHEN b.root_source_id REGEXP 'dyyjs_|touliu_tencent_' THEN '承接' -- 其他渠道:固定为日常
+                ELSE '日常'
+        END AS push_type -- 子渠道
+        ,CASE   WHEN b.root_source_id REGEXP 'dyyjs_' THEN t3.ghid_list
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' THEN t6.put_carrier_id
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN COALESCE(s.gh_id,'')
+                WHEN b.root_source_id REGEXP 'longArticles_' THEN COALESCE(l.ghid,'')
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh' AND b.root_source_id NOT REGEXP 'fwhtouliu_' THEN COALESCE(t5.ghid,'')
+                WHEN b.root_source_id REGEXP 'fwhtouliu_' THEN COALESCE(t5.ghid,'')
+                ELSE ''
+        END AS sub_channel -- 渠道类型(统一映射)
+        ,CASE   WHEN b.root_source_id REGEXP 'longArticles_' AND g.gzh_buy_root IS NOT NULL THEN '公众号买号'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NULL THEN '公众号代运营-Daily-系统'
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN '公众号合作-即转-稳定'
+                WHEN b.root_source_id REGEXP 'fwhtouliu_' THEN '服务号投流'
+                WHEN b.root_source_id REGEXP 'touliu_tencent_' THEN '小程序投流-稳定'
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh' AND b.root_source_id NOT REGEXP 'fwhtouliu_' THEN '公众号投流-稳定'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_' AND t7.rootsourceid IS NULL THEN '企微投放'
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t6.root_source_id IS NOT NULL THEN '群/企微合作-稳定' --WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN '90公众号代投'
+                WHEN b.root_source_id REGEXP 'qwsq_' AND t7.rootsourceid IS NOT NULL THEN '企微投放-存量拉群'
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN '服务号合作-Daily-自选' --WHEN b.root_source_id REGEXP 'fwhmh_' THEN '92服务号买号'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NOT NULL THEN '公众号合作-Daily-自选'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_|qwmf_' AND t7.rootsourceid IS NOT NULL THEN '微信群买粉'
+                WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN '公众号完全代投放'
+                WHEN b.root_source_id REGEXP 'fwhmh_' THEN '服务号买号'
+                ELSE '内部'
+        END AS channel_type
+        ,CASE   WHEN b.root_source_id REGEXP 'longArticles_' AND g.gzh_buy_root IS NOT NULL THEN 'longArticles_'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NULL THEN 'longArticles_'
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN 'dyyjs_'
+                WHEN b.root_source_id REGEXP 'fwhtouliu_' THEN 'fwhtouliu_'
+                WHEN b.root_source_id REGEXP 'touliu_tencent_' THEN 'touliu_tencent_'
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh' AND b.root_source_id NOT REGEXP 'fwhtouliu_' THEN 'touliu_tencentgzh_'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_' AND t7.rootsourceid IS NULL THEN 'touliu_tencentqw_'
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t6.root_source_id IS NOT NULL THEN 'touliu_tencentwbqw_' --WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN '90公众号代投'
+                WHEN b.root_source_id REGEXP 'qwsq_' AND t7.rootsourceid IS NOT NULL THEN 'qwsq_'
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN 'fwhhzdyy_' --WHEN b.root_source_id REGEXP 'fwhmh_' THEN '92服务号买号'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NOT NULL THEN 'longArticles_'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_|qwmf_' AND t7.rootsourceid IS NOT NULL THEN 'WeCom_'
+                WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN 'DaiTou_gh'
+                WHEN b.root_source_id REGEXP 'fwhmh_' THEN 'fwhmh_'
+                ELSE '内部'
+        END AS channel_type_frist -- 渠道ID(与channel_type对应)
+        ,CASE   WHEN b.root_source_id REGEXP 'longArticles_' AND g.gzh_buy_root IS NOT NULL THEN 3
+                WHEN b.root_source_id REGEXP 'longArticles_' AND g.gzh_buy_root IS NULL THEN 1
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN 2
+                WHEN b.root_source_id REGEXP 'fwhtouliu_' THEN 4
+                WHEN b.root_source_id REGEXP 'touliu_tencent_' THEN 5
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh' AND b.root_source_id NOT REGEXP 'fwhtouliu_' THEN 6
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_' AND t7.rootsourceid IS NULL THEN 7
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t6.root_source_id IS NOT NULL THEN 8 --WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN 90
+                WHEN b.root_source_id REGEXP 'qwsq_' AND t7.rootsourceid IS NOT NULL THEN 90
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN 91 --WHEN b.root_source_id REGEXP 'fwhmh_' THEN 92
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NOT NULL THEN 92
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_|qwmf_' AND t7.rootsourceid IS NOT NULL THEN 93
+                WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN 94
+                WHEN b.root_source_id REGEXP 'fwhmh_' THEN 95
+                ELSE 9999999
+        END AS channel_id
+        ,CASE   WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' --AND t9.layer_type ='特殊首层'
+                    AND t9.channel REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss'
+                    AND b.user_share_depth <= 1 THEN '外部首层'
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' --AND t9.layer_type ='非特殊首层'
+                    AND t9.channel NOT REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss'
+                    AND b.user_share_depth = 0 THEN '外部首层'
+                WHEN b.root_source_id NOT REGEXP 'touliu_tencentwbqw_|dyyqw_' AND b.user_share_depth = 0 THEN '外部首层'
+                ELSE '非外部首层'
+        END AS level_type
+        ,CASE   WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t9.channel REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss' --AND t9.layer_type ='特殊首层' 
+                THEN IF(CAST(b.user_share_depth AS INT) <= 1,0,b.user_share_depth)
+                ELSE b.user_share_depth
+        END user_share_depth
+        ,CASE   WHEN b.root_source_id REGEXP 'longArticles_' AND g.gzh_buy_root IS NOT NULL THEN '3公众号买号'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NULL THEN '1公众号代运营-Daily'
+                WHEN b.root_source_id REGEXP 'dyyjs_' THEN '2公众号代运营-即转'
+                WHEN b.root_source_id REGEXP 'fwhtouliu_' THEN '4服务号投流'
+                WHEN b.root_source_id REGEXP 'touliu_tencent_' THEN '5小程序投流'
+                WHEN b.root_source_id REGEXP 'touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh' AND b.root_source_id NOT REGEXP 'fwhtouliu_' THEN '6公众号投流'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_' AND t7.rootsourceid IS NULL THEN '7企微'
+                WHEN b.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_' AND t6.root_source_id IS NOT NULL THEN '8企微外部合作' --WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN '90公众号代投'
+                WHEN b.root_source_id REGEXP 'qwsq_' AND t7.rootsourceid IS NOT NULL THEN '90企微投放-人群包-存量拉群'
+                WHEN b.root_source_id REGEXP 'fwhhzdyy_|fwhdyy_' THEN '91服务号代运营-Daily' --WHEN b.root_source_id REGEXP 'fwhmh_' THEN '92服务号买号'
+                WHEN b.root_source_id REGEXP 'longArticles_'
+                    AND g.gzh_buy_root IS NULL
+                    AND t8.rootsourceid IS NOT NULL THEN '92公众号代运营-Daily-合作'
+                WHEN b.root_source_id REGEXP 'touliu_tencentqw_|WeCom_|qwmf_' AND t7.rootsourceid IS NOT NULL THEN '93企微买群粉'
+                WHEN b.root_source_id REGEXP 'daitou_tencentgzh|DaiTou_gh' THEN '94公众号代投'
+                WHEN b.root_source_id REGEXP 'fwhmh_' THEN '95服务号买号'
+                ELSE '内部'
+        END AS channel_type_okr
+        ,b.browse_time
+        ,b.user_share_depth
+        ,b.clienttimestamp
+FROM    base_useractive b -- 关联公众号买号分组表
+LEFT JOIN gzh_buy_group g
+ON      b.root_source_id = g.gzh_buy_root -- 关联公众号即时回复所需的ghid信息
+LEFT JOIN   (
+                SELECT  root_source_id
+                        ,CONCAT_WS(',',COLLECT_SET(put_carrier_id)) AS ghid_list
+                FROM    ad_put_flow_tencent
+                WHERE   root_source_id REGEXP 'dyyjs_'
+                GROUP BY root_source_id
+            ) t3
+ON      b.root_source_id = t3.root_source_id -- 关联公众号即时回复所需的公司信息
+LEFT JOIN loghubods.dim_company_price_info t4
+ON      b.root_source_id = t4.root_source_id
+AND     t4.dt = '${day}' -- 关联投流相关的推送类型信息
+LEFT JOIN   (
+                SELECT  rootsourceid AS root_source_id
+                        ,CASE   WHEN MAX(push_type) = '1' THEN '承接'
+                                WHEN MAX(push_type) = '2' THEN '日常'
+                                WHEN MAX(push_type) REGEXP '菜单|自动回复|即时欢迎语' THEN '承接'
+                                WHEN MAX(push_type) REGEXP '日常推送|社群' THEN '日常'
+                                WHEN MAX(push_type) REGEXP '对外信息展示' THEN '承接'
+                                WHEN MAX(push_type) REGEXP '朋友圈' THEN '日常'
+                                ELSE '未知'
+                        END AS push_type
+                        ,ghid
+                FROM    (
+                            SELECT  rootsourceid
+                                    ,CAST(push_type AS STRING) AS push_type
+                                    ,ghid
+                            FROM    loghubods.long_articles_root_source_id
+                            WHERE   dt = MAX_PT("loghubods.long_articles_root_source_id")
+                            UNION
+                            SELECT  root_source_id AS rootsourceid
+                                    ,put_type_two AS push_type
+                                    ,put_carrier_id
+                            FROM    loghubods.ad_put_flow_record_tencent_day a
+                            WHERE   a.dt = '${day}'
+                        ) 
+                GROUP BY rootsourceid
+                         ,ghid
+            ) t5
+ON      b.root_source_id = t5.root_source_id -- 关联企微外部合作的put_carrier_id
+LEFT JOIN   (
+                SELECT  root_source_id
+                        ,put_carrier_id
+                FROM    ad_put_flow_tencent
+                WHERE   put_type_one = '企微'
+                AND     root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_'
+                GROUP BY root_source_id
+                         ,put_carrier_id
+            ) t6
+ON      b.root_source_id = t6.root_source_id -- 关联服务号信息
+LEFT JOIN   (
+                SELECT  rootsourceid
+                        ,s.gh_id
+                        ,s.channel
+                FROM    loghubods.long_articles_root_source_id a
+                LEFT JOIN service_account s
+                ON      a.ghid = s.gh_id
+                WHERE   a.dt = MAX_PT('loghubods.long_articles_root_source_id')
+                UNION
+                SELECT  root_source_id AS rootsourceid
+                        ,a.put_carrier_id
+                        ,d.channel
+                FROM    loghubods.ad_put_flow_record_tencent_day a
+                LEFT JOIN   (
+                                SELECT  account.channel
+                                        ,gzh.gh_id
+                                        ,gzh.`name`
+                                        ,(CASE    gzh.type
+                                                WHEN 0 THEN '公众号'
+                                                ELSE '服务号'
+                                        END) AS type
+                                FROM    loghubods.content_platform_account account
+                                LEFT JOIN loghubods.content_platform_gzh_account gzh
+                                ON      account.id = gzh.create_account_id
+                            ) d
+                ON      a.put_carrier_id = d.gh_id
+                AND     d.type = '服务号'
+                WHERE   a.dt = '${day}'
+                AND     root_source_id REGEXP 'fwhhzdyy_|fwhdyy_'
+            ) s
+ON      b.root_source_id = s.rootsourceid
+LEFT JOIN   (
+                SELECT  root_source_id AS rootsourceid
+                        ,put_type_two AS push_type --,b.name AS accountname
+                        ,COALESCE(b.name,a.remark) AS accountname
+                FROM    loghubods.ad_put_flow_record_tencent_day a
+                LEFT JOIN   (
+                                SELECT  user_id
+                                        ,name
+                                FROM    loghubods.reply_staff
+                                WHERE   dt = MAX_PT('loghubods.reply_staff')
+                                AND     is_delete = 0
+                            ) b
+                ON      a.put_carrier_id = b.user_id
+                WHERE   dt = '${day}'
+                AND     put_type_one = '企微'
+                AND     root_source_id REGEXP 'touliu_tencentqw_|WeCom_|qwmf_|qwsq_'
+                AND     (
+                            COALESCE(b.name,a.remark) IN ('热点视频推荐','情感专家-月亮姐姐')
+                            OR      root_source_id REGEXP 'qwmf_|qwsq_'
+                )
+                GROUP BY root_source_id
+                         ,put_type_two
+                         ,COALESCE(b.name,a.remark)
+            ) t7
+ON      b.root_source_id = t7.rootsourceid -- 关联长文信息
+LEFT JOIN long_articles_info l
+ON      b.root_source_id = l.rootsourceid
+LEFT JOIN   (
+                SELECT  rootsourceid
+                        ,channel
+                        ,channel_name
+                        ,ghid
+                        ,gzh_name
+                        ,type
+                FROM    loghubods.rootsourceid_ghid_channel_mapping
+                WHERE   type = '公众号'
+                GROUP BY rootsourceid
+                         ,channel
+                         ,channel_name
+                         ,ghid
+                         ,gzh_name
+                         ,type
+            ) t8
+ON      b.root_source_id = t8.rootsourceid
+LEFT JOIN   (
+                SELECT  t1.root_source_id AS rootsourceid
+                        ,t1.put_type_two AS push_type
+                        ,t1.channel
+                        ,t2.layer_type
+                FROM    loghubods.ad_put_flow_record_tencent_day t1
+                LEFT JOIN loghubods.content_platform_account t2
+                ON      t1.channel = t2.channel
+                WHERE   t1.dt = MAX_PT('loghubods.ad_put_flow_record_tencent_day')
+                AND     t1.put_type_one = '企微'
+                AND     t1.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_|dyycd_'
+                GROUP BY t1.root_source_id
+                         ,t1.put_type_two
+                         ,t1.channel
+                         ,t2.layer_type
+            ) t9
+ON      b.root_source_id = t9.rootsourceid
+;

+ 722 - 0
table_gen/de.sql

@@ -0,0 +1,722 @@
+-- =====================================================================
+-- 用户拉活-曝光-拉回分析表 (recommend_distribution_data_total)
+-- 维度: 用户拉活量分层 × 进入小时 × 进入场景 × 进入内容品类 × 推荐内容品类 × 内容id
+-- 粒度: GROUP BY CUBE 全维度组合 + SUM 汇总
+-- =====================================================================
+
+-- DROP TABLE IF EXISTS loghubods.recommend_distribution_data_total;
+CREATE TABLE IF NOT EXISTS loghubods.recommend_distribution_data_total (
+    `用户拉活量分层`             STRING    COMMENT '用户拉活量分层(R0&新用户/R1-50等,汇总为SUM)',
+    `进入小时`                   STRING    COMMENT '进入小时(1-4/5-8等,汇总为SUM)',
+    `进入场景`                   STRING    COMMENT '进入场景(业务场景描述,汇总为SUM)',
+    `进入内容品类`               STRING    COMMENT '进入内容品类(merge_leve2维度,汇总为SUM)',
+    `推荐内容品类`               STRING    COMMENT '推荐内容品类(merge_leve2维度,汇总为SUM)',
+    `内容id`                     STRING    COMMENT '内容id(videoid,其他为兜底,汇总为SUM)',
+
+    -- ===== 基础流量指标 =====
+    `访问人数`                   BIGINT    COMMENT '去重访问人数(machinecode维度)',
+    `曝光人数`                   BIGINT    COMMENT '去重曝光人数(mid维度)',
+    `曝光人数比访问人数`         DOUBLE    COMMENT '曝光人数/访问人数 比值',
+    `曝光次数`                   BIGINT    COMMENT '曝光总次数(mid计数)',
+    `曝光次数人均`               DOUBLE    COMMENT '曝光次数/去重曝光人数 人均曝光次数',
+    `视频个数`                   BIGINT    COMMENT '去重曝光视频个数(vid维度)',
+    `单视频曝光次数`             DOUBLE    COMMENT '曝光次数/去重视频个数 单视频平均曝光次数',
+
+    -- ===== 全链路拉回 =====
+    `ALL拉回n层`                 BIGINT    COMMENT '全量拉回n层人数(多来源拉回人数求和)',
+    `ALL拉回n层比曝光次数`       DOUBLE    COMMENT '全量拉回n层人数/曝光次数 比值,保留6位小数',
+
+    -- ===== 原生拉回 & rovn =====
+    `return_n_uv_noself`         BIGINT    COMMENT '原生n层拉回人数(无自返)',
+    `rovn`                       DOUBLE    COMMENT '原生n层拉回人数/曝光次数 比值,保留6位小数',
+    `rovn_pred`                  DOUBLE    COMMENT 'rovn预估值(str_pred*rosn_pred平均值),保留6位小数',
+    `rovn_copc`                  DOUBLE    COMMENT 'rovn实际/rovn预估 比值,保留4位小数',
+
+    -- ===== STR 指标 =====
+    `str_real`                   DOUBLE    COMMENT 'str实际值(is_return_noself求和/曝光次数),保留6位小数',
+    `str_pred`                   DOUBLE    COMMENT 'str预估值(str_pred求和/曝光次数),保留6位小数',
+    `str_copc`                   DOUBLE    COMMENT 'str实际/str预估 比值,保留4位小数',
+    `str_MAE`                    DOUBLE    COMMENT 'str预估与实际的平均绝对误差,保留6位小数',
+    `STR_VAR`                    DOUBLE    COMMENT 'str预估与实际差值的方差,保留6位小数',
+    `strauc`                     DOUBLE    COMMENT 'str AUC,保留6位小数',
+    `str多维加权copc`            DOUBLE    COMMENT 'str多维加权copc,保留6位小数',
+
+    -- ===== ROSN 指标 =====
+    `rosn_real`                  DOUBLE    COMMENT 'rosn实际值(原生n层拉回人数/is_return_noself求和),保留6位小数',
+    `rosn_pred`                  DOUBLE    COMMENT 'rosn预估值(rosn_pred求和/曝光次数),保留6位小数',
+    `rosn_copc`                  DOUBLE    COMMENT 'rosn实际/rosn预估 比值,保留4位小数',
+    `rosn_实际预估diff绝对距离`  DOUBLE    COMMENT '拉回时rosn预估与实际的平均绝对距离,保留6位小数',
+    `rosn_实际预估高低估分布比例` DOUBLE   COMMENT '拉回时rosn预估与实际差值的方差,保留6位小数',
+
+    -- ===== B链 (分享→点击) =====
+    `Buv1层拉回人数`             BIGINT    COMMENT 'B端uv1层拉回人数(is_return_noself求和)',
+    `rov0`                       DOUBLE    COMMENT 'B端uv1层拉回人数/曝光次数 比值,保留6位小数',
+    `rov0预估`                   BIGINT    COMMENT 'rov0预估值(固定为0)',
+    `rov0copc`                   BIGINT    COMMENT 'rov0copc值(固定为0)',
+    `ros0`                       DOUBLE    COMMENT 'ros0实际值(B端uv1层拉回人数/分享次数),保留6位小数',
+    `ros0预估`                   BIGINT    COMMENT 'ros0预估值(固定为0)',
+    `ros0copc`                   BIGINT    COMMENT 'ros0copc值(固定为0)',
+    `Bnuvn层拉回人数`            BIGINT    COMMENT 'B端nuvn层拉回人数(原生n层拉回人数一致)',
+    `rorn_b`                     DOUBLE    COMMENT 'B端n层拉回率(Bnuvn/uv1层拉回人数),保留6位小数',
+    `ror1单层_b`                 DOUBLE    COMMENT 'B端1层拉回率(b1/uv1层拉回人数),保留6位小数',
+    `ror2单层_b`                 DOUBLE    COMMENT 'B端2层拉回率(b2/b1),保留6位小数',
+
+    -- ===== B链 T+1 =====
+    `Bnuvn层拉回人数_t1`         DOUBLE    COMMENT 'T1维度B端nuvn层拉回人数,保留6位小数',
+    `rorn_b_t1`                  DOUBLE    COMMENT 'T1维度B端n层拉回率,保留6位小数',
+    `ror1单层_b_t1`              DOUBLE    COMMENT 'T1维度B端1层拉回率,保留6位小数',
+    `ror2单层_b_t1`              DOUBLE    COMMENT 'T1维度B端2层拉回率,保留6位小数',
+
+    -- ===== C链 (二次分享→点击) =====
+    `cn`                         BIGINT    COMMENT 'C端拉回n层人数',
+    `rorn_c`                     DOUBLE    COMMENT 'C端n层拉回率(cn/原生n层拉回人数)',
+    `ror1_c`                     DOUBLE    COMMENT 'C端1层拉回率(c/原生n层拉回人数)',
+    `vor单层_c`                  DOUBLE    COMMENT 'C端单层视频访问率(cviews/原生n层拉回人数)',
+    `vor单层预估`                BIGINT    COMMENT 'C端单层视频访问率预估(固定为0)',
+    `vor单层copc`                BIGINT    COMMENT 'C端单层视频访问率copc(固定为0)',
+
+    -- ===== D链 (session内后续曝光传播) =====
+    `a`                          BIGINT    COMMENT 'D端去重访问人数(machinecode维度)',
+    `dn`                         BIGINT    COMMENT 'D端拉回n层人数',
+    `rorn_d`                     DOUBLE    COMMENT 'D端n层拉回率(dn/D端去重访问人数),保留6位小数',
+    `ror1_d`                     DOUBLE    COMMENT 'D端1层拉回率(d1/D端去重访问人数),保留6位小数',
+    `vor_d`                      DOUBLE    COMMENT 'D端视频访问率(g.mid计数/D端去重访问人数)'
+)
+COMMENT '用户拉活-曝光-拉回分析表'
+PARTITIONED BY (
+    dt STRING COMMENT '统计日期,格式yyyyMMdd'
+);
+
+
+-- =====================================================================
+-- CTE: 基础样本提取 + 特征工程
+-- =====================================================================
+
+WITH
+-- [1] 原始样本: 从推荐算法样本表取数,解析 scoresMap
+t_raw AS (
+    SELECT  *
+            ,REPLACE(GET_JSON_OBJECT(extend_alg, '$.scoresMap'), "\\", "") AS scoresmap
+            ,CASE
+                WHEN page IN ("回流后沉浸页&内页feed", "详情后沉浸页", "首页feed", "详情页") THEN "推荐"
+                WHEN page IN ("回流页", "其他")                                               THEN "非推荐"
+                ELSE "其他"
+             END AS page_type
+    FROM    loghubods.dwd_recsys_alg_sample_all_20250212
+    WHERE   dt = '${bizdate}'
+    -- AND     apptype IN ("0","4")
+    AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+    AND     abcode NOT IN ("ab100")
+    AND     extend_alg IS NOT NULL
+    AND     GET_JSON_OBJECT(extend_alg, '$.scoresMap') IS NOT NULL
+)
+
+-- [2] 过滤: 只保留推荐页面
+,t_filtered AS (
+    SELECT  *
+    FROM    t_raw
+    WHERE   page_type = "推荐"
+)
+
+-- [3] 特征提取: 维度映射 + 模型分数解析
+,t_base AS (
+    SELECT  dt
+            ,apptype
+            ,CASE
+                WHEN apptype IN ("4") AND abcode IN ("ab0","ab1") THEN "实验组-先验地域降权"
+                WHEN apptype IN ("4") AND abcode IN ("ab6","ab7") THEN "实验组-str+校准&ros-统计量"
+                WHEN apptype IN ("4") AND abcode IN ("ab8","ab9") THEN "实验组-str+校准"
+                WHEN apptype IN ("4") AND abcode IN ("ab2","ab3") THEN "对照组"
+                WHEN apptype IN ("4") AND abcode IN ("ab4","ab5") THEN "ab4-5"
+                ELSE "其他"
+             END AS abcode
+            ,page_type AS page
+            ,mid
+            ,vid
+            ,is_share
+            ,share_cnt
+            ,is_return_1
+            ,is_return_n
+            ,is_return_noself
+            ,return_1_uv
+            ,return_n_uv
+            ,return_n_uv_noself
+            ,new_exposure_cnt
+            ,flowpool
+            ,scoresmap
+            ,subsessionid
+            ,CAST(GET_JSON_OBJECT(scoresmap, '$.fmRov') AS DOUBLE)                            AS str_pred
+            ,1.22 * POW(CAST(GET_JSON_OBJECT(scoresmap, '$.NorXGBScore') AS DOUBLE), 1.15)    AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(scoresmap, '$.hasReturnRovScore') AS DOUBLE)                 AS rosn_stat
+            ,GET_JSON_OBJECT(v1_feature, '$.title')                                            AS vid_title
+    FROM    t_filtered
+)
+
+
+-- =====================================================================
+-- 主查询: INSERT OVERWRITE → 多维度 CUBE 聚合
+-- =====================================================================
+
+-- SELECT * FROM loghubods.recommend_distribution_data_total WHERE dt = 20260204 ORDER BY 访问人数 DESC
+
+INSERT OVERWRITE TABLE loghubods.recommend_distribution_data_total PARTITION (dt = '${bizdate}')
+SELECT
+        -- ==================== 维度列 ====================
+
+        -- 用户拉活量分层
+        CASE WHEN grouping(
+                    COALESCE(
+                        CASE
+                            WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                            WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                            WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                            ELSE e.type
+                        END
+                    , '-')
+                 ) = 1
+             THEN 'SUM'
+             ELSE NVL(
+                    COALESCE(
+                        CASE
+                            WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                            WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                            WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                            ELSE e.type
+                        END
+                    , '-')
+                 , 'SUM')
+        END                                                                     AS 用户拉活量分层
+
+        -- 进入小时
+        ,CASE WHEN grouping(
+                    COALESCE(
+                        CASE
+                            WHEN in_hour >= 1  AND in_hour <= 4  THEN '1-4'
+                            WHEN in_hour >= 5  AND in_hour <= 8  THEN '5-8'
+                            WHEN in_hour >= 9  AND in_hour <= 12 THEN '9-12'
+                            WHEN in_hour >= 13 AND in_hour <= 16 THEN '13-16'
+                            WHEN in_hour >= 17 AND in_hour <= 20 THEN '17-20'
+                            WHEN in_hour >= 21 AND in_hour <= 24 THEN '21-24'
+                            ELSE '-'
+                        END
+                    , '-')
+                 ) = 1
+              THEN 'SUM'
+              ELSE NVL(
+                    COALESCE(
+                        CASE
+                            WHEN in_hour >= 1  AND in_hour <= 4  THEN '1-4'
+                            WHEN in_hour >= 5  AND in_hour <= 8  THEN '5-8'
+                            WHEN in_hour >= 9  AND in_hour <= 12 THEN '9-12'
+                            WHEN in_hour >= 13 AND in_hour <= 16 THEN '13-16'
+                            WHEN in_hour >= 17 AND in_hour <= 20 THEN '17-20'
+                            WHEN in_hour >= 21 AND in_hour <= 24 THEN '21-24'
+                            ELSE '-'
+                        END
+                    , '-')
+                 , 'SUM')
+        END                                                                     AS 进入小时
+
+        -- 进入场景
+        ,CASE WHEN grouping(CASE WHEN f.scene_id IS NOT NULL THEN f.scene_desc ELSE '其他' END) = 1
+              THEN 'SUM'
+              ELSE NVL(CASE WHEN f.scene_id IS NOT NULL THEN f.scene_desc ELSE '其他' END, 'SUM')
+        END                                                                     AS 进入场景
+
+        -- 进入内容品类
+        ,CASE WHEN grouping(CASE WHEN m.merge_leve2 IS NOT NULL THEN d.merge_leve2 ELSE '其他' END) = 1
+              THEN 'SUM'
+              ELSE NVL(CASE WHEN m.merge_leve2 IS NOT NULL THEN d.merge_leve2 ELSE '其他' END, 'SUM')
+        END                                                                     AS 进入内容品类
+
+        -- 推荐内容品类
+        ,CASE WHEN grouping(CASE WHEN l.merge_leve2 IS NOT NULL THEN h.merge_leve2 ELSE '其他' END) = 1
+              THEN 'SUM'
+              ELSE NVL(CASE WHEN l.merge_leve2 IS NOT NULL THEN h.merge_leve2 ELSE '其他' END, 'SUM')
+        END                                                                     AS 推荐内容品类
+
+        -- 内容id
+        ,CASE WHEN grouping(COALESCE(CASE WHEN i.merge_leve2 IS NOT NULL THEN i.videoid ELSE '其他' END, '-')) = 1
+              THEN 'SUM'
+              ELSE NVL(COALESCE(CASE WHEN i.merge_leve2 IS NOT NULL THEN i.videoid ELSE '其他' END, '-'), 'SUM')
+        END                                                                     AS 内容id
+
+        -- ==================== 基础流量指标 ====================
+        ,COUNT(DISTINCT a.machinecode)                                          AS 访问人数
+        ,COUNT(DISTINCT j.mid)                                                  AS 曝光人数
+        ,COUNT(DISTINCT j.mid) / COUNT(DISTINCT a.machinecode)                  AS 曝光人数比访问人数
+        ,COUNT(j.mid)                                                           AS 曝光次数
+        ,COUNT(j.mid) / COUNT(DISTINCT j.mid)                                   AS 曝光次数人均
+        ,COUNT(DISTINCT j.vid)                                                  AS 视频个数
+        ,COUNT(j.mid) / COUNT(DISTINCT j.vid)                                   AS 单视频曝光次数
+
+        -- ==================== 全链路拉回 ====================
+        ,SUM(return_n_uv_noself) + SUM(cc.cn) + SUM(dd.dn)                     AS ALL拉回n层
+        ,ROUND(COALESCE(
+            (SUM(return_n_uv_noself) + SUM(cc.cn) + SUM(dd.dn)) / COUNT(j.mid)
+        , 0), 6)                                                                AS ALL拉回n层比曝光次数
+
+        -- ==================== 原生拉回 & rovn ====================
+        ,SUM(return_n_uv_noself)                                                AS return_n_uv_noself
+        ,ROUND(SUM(return_n_uv_noself) / COUNT(j.mid), 6)                      AS rovn
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                    AS rovn_pred
+        ,ROUND(
+            (SUM(return_n_uv_noself) / COUNT(j.mid))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                    AS rovn_copc
+
+        -- ==================== STR 指标 ====================
+        ,ROUND(COALESCE(SUM(is_return_noself) / COUNT(j.mid), 0), 6)           AS str_real
+        ,ROUND(COALESCE(SUM(str_pred)         / COUNT(j.mid), 0), 6)           AS str_pred
+        ,ROUND(
+            (SUM(is_return_noself) / COUNT(j.mid))
+            / NULLIF(SUM(str_pred) / COUNT(j.mid), 0)
+        , 4)                                                                    AS str_copc
+        ,ROUND(AVG(ABS(str_pred - is_return_noself)), 6)                       AS str_MAE
+        ,ROUND(VARIANCE(str_pred - is_return_noself), 6)                       AS STR_VAR
+        ,0                                                                      AS strauc
+        ,0                                                                      AS str多维加权copc
+
+        -- ==================== ROSN 指标 ====================
+        ,ROUND(COALESCE(
+            SUM(return_n_uv_noself) / NULLIF(SUM(is_return_noself), 0)
+        , 0), 6)                                                                AS rosn_real
+        ,ROUND(COALESCE(SUM(rosn_pred) / COUNT(j.mid), 0), 6)                 AS rosn_pred
+        ,ROUND(
+            (SUM(return_n_uv_noself) / NULLIF(SUM(is_return_noself), 0))
+            / NULLIF(SUM(rosn_pred) / COUNT(1), 0)
+        , 4)                                                                    AS rosn_copc
+        ,ROUND(AVG(
+            CASE WHEN is_return_noself = 1
+                 THEN ABS(rosn_pred - return_n_uv_noself)
+            END
+        ), 6)                                                                   AS rosn_实际预估diff绝对距离
+        ,ROUND(VARIANCE(
+            CASE WHEN is_return_noself = 1
+                 THEN rosn_pred - return_n_uv_noself
+            END
+        ), 6)                                                                   AS rosn_实际预估高低估分布比例
+
+        -- ==================== B链: 分享→点击 ====================
+        ,SUM(is_return_noself)                                                  AS Buv1层拉回人数
+        ,ROUND(SUM(is_return_noself) / COUNT(j.mid), 6)                        AS rov0
+        ,0                                                                      AS rov0预估
+        ,0                                                                      AS rov0copc
+        ,ROUND(COALESCE(
+            SUM(is_return_noself) / NULLIF(SUM(share_cnt), 0)
+        , 0), 6)                                                                AS ros0
+        ,0                                                                      AS ros0预估
+        ,0                                                                      AS ros0copc
+        ,SUM(return_n_uv_noself)                                                AS Bnuvn层拉回人数
+        ,ROUND(COALESCE(SUM(return_n_uv_noself) / SUM(is_return_noself), 0), 6) AS rorn_b
+        ,ROUND(COALESCE(SUM(k.b1)               / SUM(is_return_noself), 0), 6) AS ror1单层_b
+        ,ROUND(COALESCE(SUM(k.b2)               / SUM(k.b1),             0), 6) AS ror2单层_b
+
+        -- ==================== B链 T+1 ====================
+        ,ROUND(COALESCE(SUM(k1.bn), 0), 6)                                     AS Bnuvn层拉回人数_t1
+        ,ROUND(COALESCE(SUM(k1.bn) / SUM(k1.b),  0), 6)                       AS rorn_b_t1
+        ,ROUND(COALESCE(SUM(k1.b1) / SUM(k1.b),  0), 6)                       AS ror1单层_b_t1
+        ,ROUND(COALESCE(SUM(k1.b2) / SUM(k1.b1), 0), 6)                       AS ror2单层_b_t1
+
+        -- ==================== C链: 二次分享 ====================
+        ,SUM(cc.cn)                                                             AS cn
+        ,SUM(cc.cn)     / SUM(return_n_uv_noself)                              AS rorn_c
+        ,SUM(cc.c)      / SUM(return_n_uv_noself)                              AS ror1_c
+        ,SUM(cc.cviews) / SUM(return_n_uv_noself)                              AS vor单层_c
+        ,0                                                                      AS vor单层预估
+        ,0                                                                      AS vor单层copc
+
+        -- ==================== D链: session内后续曝光传播 ====================
+        ,COUNT(DISTINCT b.machinecode)                                          AS a
+        ,SUM(dd.dn)                                                             AS dn
+        ,ROUND(COALESCE(SUM(dd.dn) / COUNT(DISTINCT b.machinecode), 0), 6)    AS rorn_d
+        ,ROUND(COALESCE(SUM(dd.d1) / COUNT(DISTINCT b.machinecode), 0), 6)    AS ror1_d
+        ,COUNT(g.mid) / COUNT(DISTINCT b.machinecode)                           AS vor_d
+
+
+-- =====================================================================
+-- FROM + JOINs
+-- =====================================================================
+
+FROM    (
+            -- [a] 用户活跃日志 + 进入小时
+            SELECT  *
+                    ,TO_CHAR(FROM_UNIXTIME(a.clienttimestamp / 1000), 'HH') + 1 AS in_hour
+            FROM    loghubods.useractive_log a
+            WHERE   a.dt = '${bizdate}'
+        ) a
+
+-- [b] 分享点击日志 (topic=click)
+LEFT JOIN (
+            SELECT  DISTINCT
+                    machinecode
+                    ,sessionid
+                    ,subsessionid
+                    ,pagesource
+                    ,topic
+                    ,shareid
+                    ,clickobjectid
+                    ,shareobjectid
+                    ,clientip
+                    ,CASE
+                        WHEN topic = 'click' THEN clickobjectid
+                        WHEN topic = 'share' THEN shareobjectid
+                     END AS videoid
+                    ,sharetitleid
+                    ,sharetitle
+                    ,shareimageurl
+                    ,rootsharemid
+                    ,clienttimestamp
+                    ,FROM_UNIXTIME(clienttimestamp / 1000)                                         AS click_time
+                    ,GET_JSON_OBJECT(videocdm.Ip2RegionAnalyse(clientip), "$.province")            AS click_province
+                    ,GET_JSON_OBJECT(videocdm.Ip2RegionAnalyse(clientip), "$.city")                AS click_city
+                    ,TO_CHAR(FROM_UNIXTIME(clienttimestamp / 1000), 'HH') + 1                     AS click_hour
+            FROM    loghubods.user_share_log
+            WHERE   dt = '${bizdate}'
+            AND     topic = 'click'
+        ) b
+ON      a.machinecode  = b.machinecode
+AND     a.subsessionid = b.subsessionid
+
+-- [c] 视频元信息
+LEFT JOIN videoods.wx_video c
+ON      b.videoid = c.id
+
+-- [d] 点击视频品类标签
+LEFT JOIN loghubods.video_merge_tag d
+ON      b.videoid = d.videoid
+
+-- [e] 用户拉活量分层 (R0/R1-50/R_180_330/...)
+LEFT JOIN (
+            SELECT  DISTINCT type, openid
+            FROM    loghubods.mid_share_return_people_1year
+            WHERE   dt = '${bizdate-1}'
+            AND     type IS NOT NULL
+            AND     type != 'S_ALL'
+            AND     type NOT REGEXP 'R50'
+        ) e
+ON      SUBSTRING_INDEX(a.machinecode, 'weixin_openid_', -1) = e.openid
+
+-- [f] TOP5 进入场景
+LEFT JOIN (
+            SELECT  a.scene_id
+                    ,a.scene_desc
+                    ,COUNT(DISTINCT b.machinecode) AS cnt
+            FROM    loghubods.wechat_miniprogram_scene_simple a
+            LEFT JOIN loghubods.useractive_log b
+            ON      a.scene_id = b.sencetype
+            AND     b.dt = '${bizdate}'
+            GROUP BY a.scene_id, a.scene_desc
+            ORDER BY cnt DESC
+            LIMIT   5
+        ) f
+ON      a.sencetype = f.scene_id
+
+-- [g] 推荐页视频播放
+LEFT JOIN (
+            SELECT  DISTINCT mid, subsessionid, videoid
+            FROM    loghubods.video_action_log_rp
+            WHERE   dt = '${bizdate}'
+            AND     businesstype = 'videoView'
+            AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+        ) g
+ON      b.machinecode  = g.mid
+AND     b.subsessionid = g.subsessionid
+
+-- [h] 推荐视频品类标签
+LEFT JOIN loghubods.video_merge_tag h
+ON      g.videoid = h.videoid
+
+-- [i] 热门视频 (按品类 TOP1, 曝光>10w)
+LEFT JOIN (
+            SELECT  merge_leve2, videoid
+            FROM    (
+                        SELECT  b.merge_leve2
+                                ,a.videoid
+                                ,COUNT(1)                                                        AS view
+                                ,ROW_NUMBER() OVER (PARTITION BY b.merge_leve2 ORDER BY COUNT(1) DESC) AS rank
+                        FROM    loghubods.video_action_log_rp a
+                        LEFT JOIN loghubods.video_merge_tag b
+                        ON      a.videoid = b.videoid
+                        WHERE   dt = '${bizdate}'
+                        AND     businesstype = 'videoView'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                        GROUP BY b.merge_leve2, a.videoid
+                        HAVING  view > 100000
+                    )
+            WHERE   rank <= 1
+        ) i
+ON      g.videoid = i.videoid
+
+-- [j] 曝光样本 (t_base CTE)
+LEFT JOIN t_base j
+ON      g.mid          = j.mid
+AND     g.subsessionid = j.subsessionid
+AND     g.videoid      = j.vid
+
+-- [k] B链: 当天分享→点击裂变 (sharedepth 1~4)
+LEFT JOIN (
+            SELECT  a.machinecode                                                               AS mid
+                    ,a.subsessionid
+                    ,a.videoid                                                                  AS vid
+                    ,COUNT(DISTINCT CASE WHEN a.machinecode <> b.machinecode                              THEN b.machinecode END) AS bn
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 1 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 2 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b1
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 3 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b2
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 4 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b3
+            FROM    (
+                        SELECT  DISTINCT machinecode, shareobjectid AS videoid, recomTraceId,
+                                subsessionid, sharedepth, shareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'share'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                    ) a
+            LEFT JOIN (
+                        SELECT  DISTINCT machinecode, clickobjectid, recomTraceId,
+                                subsessionid, sharedepth, rootshareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'click'
+                    ) b
+            ON      a.shareid = b.rootshareid
+            GROUP BY a.machinecode, a.subsessionid, a.videoid
+        ) k
+ON      g.mid          = k.mid
+AND     g.subsessionid = k.subsessionid
+AND     g.videoid      = k.vid
+
+-- [k1] B链 T+1: 跨天分享→点击裂变
+LEFT JOIN (
+            SELECT  a.machinecode                                                               AS mid
+                    ,a.subsessionid
+                    ,a.videoid                                                                  AS vid
+                    ,COUNT(DISTINCT CASE WHEN a.machinecode <> b.machinecode                              THEN b.machinecode END) AS bn
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 1 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 2 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b1
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 3 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b2
+                    ,COUNT(DISTINCT CASE WHEN b.sharedepth = 4 AND a.machinecode <> b.machinecode         THEN b.machinecode END) AS b3
+            FROM    (
+                        SELECT  DISTINCT machinecode, shareobjectid AS videoid, recomTraceId,
+                                subsessionid, sharedepth, shareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'share'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                    ) a
+            LEFT JOIN (
+                        SELECT  DISTINCT machinecode, clickobjectid, recomTraceId,
+                                subsessionid, sharedepth, rootshareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt >= '${bizdate}'
+                        AND     dt <= '${bizdate+1}'       -- T+1 跨天
+                        AND     topic = 'click'
+                    ) b
+            ON      a.shareid = b.rootshareid
+            GROUP BY a.machinecode, a.subsessionid, a.videoid
+        ) k1
+ON      g.mid          = k1.mid
+AND     g.subsessionid = k1.subsessionid
+AND     g.videoid      = k1.vid
+
+-- [l] TOP10 推荐品类 (按播放量)
+LEFT JOIN (
+            SELECT  b.merge_leve2
+                    ,COUNT(1) AS view
+            FROM    loghubods.video_action_log_rp a
+            LEFT JOIN loghubods.video_merge_tag b
+            ON      a.videoid = b.videoid
+            WHERE   dt = '${bizdate}'
+            AND     businesstype = 'videoView'
+            AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+            AND     b.merge_leve2 IS NOT NULL
+            GROUP BY b.merge_leve2
+            ORDER BY view DESC
+            LIMIT   10
+        ) l
+ON      h.merge_leve2 = l.merge_leve2
+
+-- [m] TOP1 点击品类 (按点击人数)
+LEFT JOIN (
+            SELECT  b.merge_leve2
+                    ,COUNT(DISTINCT machinecode) AS click
+            FROM    loghubods.user_share_log a
+            LEFT JOIN loghubods.video_merge_tag b
+            ON      a.clickobjectid = b.videoid
+            WHERE   dt = '${bizdate}'
+            AND     topic = 'click'
+            AND     b.merge_leve2 IS NOT NULL
+            GROUP BY b.merge_leve2
+            ORDER BY click DESC
+            LIMIT   1
+        ) m
+ON      d.merge_leve2 = m.merge_leve2
+
+-- [cc] C链: 二次分享 (分享→点击→再分享→再点击 + 视频播放)
+LEFT JOIN (
+            SELECT  a.machinecode                                                               AS mid
+                    ,a.subsessionid
+                    ,a.videoid                                                                  AS vid
+                    ,COUNT(DISTINCT CASE WHEN b1.machinecode <> b2.machinecode THEN b2.machinecode END)  AS cn
+                    ,COUNT(DISTINCT
+                        CASE WHEN b2.sharedepth = 1 AND b1.machinecode <> b2.machinecode
+                             THEN b2.machinecode
+                        END
+                    )                                                                           AS c
+                    ,COUNT(c.mid)                                                               AS cviews
+            FROM    (
+                        -- 一次分享
+                        SELECT  DISTINCT machinecode, shareobjectid AS videoid, recomTraceId,
+                                subsessionid, sharedepth, shareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'share'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                    ) a
+            LEFT JOIN (
+                        -- 一次点击
+                        SELECT  DISTINCT machinecode, clickobjectid, recomTraceId,
+                                subsessionid, sharedepth, rootshareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'click'
+                    ) b
+            ON      a.shareid = b.rootshareid
+            LEFT JOIN (
+                        -- 二次分享 (点击者再分享)
+                        SELECT  DISTINCT machinecode, shareobjectid, recomTraceId,
+                                subsessionid, sharedepth, shareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'share'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                    ) b1
+            ON      b.machinecode  = b1.machinecode
+            AND     b.subsessionid = b1.subsessionid
+            LEFT JOIN (
+                        -- 二次点击
+                        SELECT  DISTINCT machinecode, clickobjectid, recomTraceId,
+                                subsessionid, sharedepth, shareid, rootshareid
+                        FROM    loghubods.user_share_log
+                        WHERE   dt = '${bizdate}'
+                        AND     topic = 'click'
+                    ) b2
+            ON      b1.shareid = b2.rootshareid
+            LEFT JOIN (
+                        -- 二次点击者的视频播放
+                        SELECT  DISTINCT mid, subsessionid, videoid
+                        FROM    loghubods.video_action_log_rp
+                        WHERE   dt = '${bizdate}'
+                        AND     businesstype = 'videoView'
+                        AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                    ) c
+            ON      b2.machinecode = c.mid
+            AND     b2.subsessionid = c.subsessionid
+            GROUP BY a.machinecode, a.subsessionid, a.videoid
+        ) cc
+ON      g.mid          = cc.mid
+AND     g.subsessionid = cc.subsessionid
+AND     g.videoid      = cc.vid
+
+-- [dd] D链: session内后续曝光传播 (窗口函数累计后续拉回)
+LEFT JOIN (
+            SELECT  *
+                    ,COALESCE(
+                        SUM(回流)  OVER (PARTITION BY mid, subsessionid ORDER BY rn ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING)
+                    , 0) AS dn
+                    ,COALESCE(
+                        SUM(回流1) OVER (PARTITION BY mid, subsessionid ORDER BY rn ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING)
+                    , 0) AS d1
+            FROM    (
+                        SELECT  a.mid                                                           AS mid
+                                ,a.subsessionid
+                                ,a.videoid                                                      AS vid
+                                ,COUNT(DISTINCT b.shareid)                                      AS 分享次数
+                                ,COUNT(DISTINCT
+                                    CASE WHEN c.machinecode <> b.machinecode
+                                         THEN c.machinecode
+                                    END
+                                )                                                               AS 回流
+                                ,COUNT(DISTINCT
+                                    CASE WHEN c.machinecode <> b.machinecode AND c.sharedepth = 1
+                                         THEN c.machinecode
+                                    END
+                                )                                                               AS 回流1
+                                ,ROW_NUMBER() OVER (PARTITION BY a.subsessionid ORDER BY a.logtimestamp DESC) AS rn
+                        FROM    (
+                                    SELECT  DISTINCT mid, subsessionid, videoid, logtimestamp
+                                    FROM    loghubods.video_action_log_rp
+                                    WHERE   dt = '${bizdate}'
+                                    AND     businesstype = 'videoView'
+                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                ) a
+                        LEFT JOIN (
+                                    SELECT  DISTINCT machinecode, shareobjectid AS videoid, recomTraceId,
+                                            subsessionid, sharedepth, shareid, clienttimestamp
+                                    FROM    loghubods.user_share_log
+                                    WHERE   dt = '${bizdate}'
+                                    AND     topic = 'share'
+                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                ) b
+                        ON      a.mid          = b.machinecode
+                        AND     a.subsessionid = b.subsessionid
+                        AND     a.videoid      = b.videoid
+                        LEFT JOIN (
+                                    SELECT  DISTINCT machinecode, clickobjectid, recomTraceId,
+                                            subsessionid, sharedepth, rootshareid
+                                    FROM    loghubods.user_share_log
+                                    WHERE   dt = '${bizdate}'
+                                    AND     topic = 'click'
+                                ) c
+                        ON      b.shareid = c.rootshareid
+                        GROUP BY a.mid, a.subsessionid, a.videoid, a.logtimestamp
+                    )
+        ) dd
+ON      g.mid          = dd.mid
+AND     g.subsessionid = dd.subsessionid
+AND     g.videoid      = dd.vid
+
+
+-- =====================================================================
+-- GROUP BY CUBE: 全维度组合聚合
+-- =====================================================================
+
+GROUP BY CUBE(
+            -- 用户拉活量分层
+            COALESCE(
+                CASE
+                    WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                    WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                    WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                    ELSE e.type
+                END
+            , '-')
+
+            -- 进入小时
+            ,COALESCE(
+                CASE
+                    WHEN in_hour >= 1  AND in_hour <= 4  THEN '1-4'
+                    WHEN in_hour >= 5  AND in_hour <= 8  THEN '5-8'
+                    WHEN in_hour >= 9  AND in_hour <= 12 THEN '9-12'
+                    WHEN in_hour >= 13 AND in_hour <= 16 THEN '13-16'
+                    WHEN in_hour >= 17 AND in_hour <= 20 THEN '17-20'
+                    WHEN in_hour >= 21 AND in_hour <= 24 THEN '21-24'
+                    ELSE '-'
+                END
+            , '-')
+
+            -- 进入场景
+            ,CASE WHEN f.scene_id IS NOT NULL THEN f.scene_desc ELSE '其他' END
+
+            -- 进入内容品类
+            ,CASE WHEN m.merge_leve2 IS NOT NULL THEN d.merge_leve2 ELSE '其他' END
+
+            -- 推荐内容品类
+            ,CASE WHEN l.merge_leve2 IS NOT NULL THEN h.merge_leve2 ELSE '其他' END
+
+            -- 内容id
+            ,COALESCE(CASE WHEN i.merge_leve2 IS NOT NULL THEN i.videoid ELSE '其他' END, '-')
+        )
+
+ORDER BY 访问人数 DESC
+;

+ 194 - 0
table_gen/test_1.sql

@@ -0,0 +1,194 @@
+WITH
+-- 用户拉活量分层
+t_user_type AS (
+    SELECT  DISTINCT type, openid
+    FROM    loghubods.mid_share_return_people_1year
+    WHERE   dt = TO_CHAR(DATEADD(TO_DATE('${dt}','YYYYMMDD'),-1,'dd'),'YYYYMMDD')
+    AND     type IS NOT NULL
+    AND     type != 'S_ALL'
+    AND     type NOT REGEXP 'R50'
+)
+-- 模型预估分数
+,t_score AS (
+    SELECT  apptype
+            ,videoid
+            ,recommendtraceid
+            ,scoresmap
+            ,sortscore
+    FROM    (
+                SELECT  apptype
+                        ,videoid
+                        ,recommendtraceid
+                        ,scoresmap
+                        ,sortscore
+                        ,ROW_NUMBER() OVER (PARTITION BY apptype,videoid,recommendtraceid) AS rn
+                FROM    loghubods.statistics_log_hour
+                WHERE   dt = '${dt}'
+                AND     scoresmap IS NOT NULL
+            )
+    WHERE   rn = 1
+)
+-- 宽表
+,t_wide AS (
+    SELECT  base.*
+            ,CASE WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                  WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                  WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                  ELSE e.type
+             END AS user_type
+            ,vt_head.merge_leve2  AS head_merge_leve2
+            ,vt_vid.merge_leve2   AS vid_merge_leve2
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.fmRov') AS DOUBLE) AS str_pred
+            ,1.22*POW(CAST(GET_JSON_OBJECT(e1.scoresmap,'$.NorXGBScore') AS DOUBLE),1.15) AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.hasReturnRovScore') AS DOUBLE) AS rosn_pred_origin
+            ,e1.sortscore
+            ,CASE
+                WHEN CAST(hh AS INT) BETWEEN 0  AND 3  THEN '00-03'
+                WHEN CAST(hh AS INT) BETWEEN 4  AND 7  THEN '04-07'
+                WHEN CAST(hh AS INT) BETWEEN 8  AND 11 THEN '08-11'
+                WHEN CAST(hh AS INT) BETWEEN 12 AND 15 THEN '12-15'
+                WHEN CAST(hh AS INT) BETWEEN 16 AND 19 THEN '16-19'
+                WHEN CAST(hh AS INT) BETWEEN 20 AND 23 THEN '20-23'
+                ELSE '-'
+             END AS hh_bucket
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    LEFT JOIN t_user_type e
+    ON      SUBSTRING_INDEX(base.mid,'weixin_openid_',-1) = e.openid
+    LEFT JOIN loghubods.video_merge_tag vt_head
+    ON      base.headvideoid = vt_head.videoid
+    LEFT JOIN loghubods.video_merge_tag vt_vid
+    ON      base.vid = vt_vid.videoid
+    LEFT JOIN t_score e1
+    ON      base.apptype = e1.apptype
+    AND     base.vid = e1.videoid
+    AND     base.recomtraceid = e1.recommendtraceid
+    WHERE   base.dt = '${dt}'
+)
+
+SELECT
+        -- ==================== 维度列 ====================
+        CASE WHEN GROUPING(user_type) = 1 THEN 'SUM' ELSE NVL(user_type, 'SUM') END              AS user_type
+        ,CASE WHEN GROUPING(hh_bucket) = 1 THEN 'SUM' ELSE NVL(hh_bucket, 'SUM') END              AS hh_bucket
+        ,CASE WHEN GROUPING(head_merge_leve2) = 1 THEN 'SUM' ELSE NVL(head_merge_leve2, 'SUM') END AS head_merge_leve2
+        ,CASE WHEN GROUPING(vid_merge_leve2) = 1 THEN 'SUM' ELSE NVL(vid_merge_leve2, 'SUM') END   AS vid_merge_leve2
+
+        -- ==================== 基础流量 ====================
+        ,COUNT(1)                                                                       AS exposure_cnt
+        ,COUNT(DISTINCT mid)                                                            AS exposure_uv
+        ,COUNT(DISTINCT vid)                                                            AS vid_cnt
+        ,ROUND(COUNT(1) / COUNT(DISTINCT mid), 4)                                      AS exposure_per_user
+
+        -- ==================== 分享 ====================
+        ,SUM(CAST(is_share AS BIGINT))                                                  AS share_exposure_cnt
+        ,SUM(CAST(share_cnt AS BIGINT))                                                 AS share_cnt
+
+        -- ==================== STR 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS str_real
+        ,ROUND(COALESCE(SUM(str_pred) / NULLIF(COUNT(1), 0), 0), 6)                          AS str_pred
+        ,ROUND(
+            (SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(SUM(str_pred) / NULLIF(COUNT(1), 0), 0)
+        , 4)                                                                                   AS str_copc
+        ,ROUND(AVG(ABS(str_pred - CAST(is_return_noself AS BIGINT))), 6)                      AS str_mae
+        ,ROUND(VARIANCE(str_pred - CAST(is_return_noself AS BIGINT)), 6)                      AS str_var
+
+        -- ==================== ROSN 指标 ====================
+        ,ROUND(COALESCE(
+            SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0)
+        , 0), 6)                                                                               AS rosn_real
+        ,ROUND(COALESCE(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0), 6)  AS rosn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0))
+            / NULLIF(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0)
+        , 4)                                                                                   AS rosn_copc
+        ,ROUND(AVG(rosn_pred_origin), 6)                                                      AS rosn_pred_origin
+        ,ROUND(AVG(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN ABS(rosn_pred - CAST(return_n_uv_noself AS BIGINT))
+            END
+        ), 6)                                                                                  AS rosn_mae
+        ,ROUND(VARIANCE(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN rosn_pred - CAST(return_n_uv_noself AS BIGINT)
+            END
+        ), 6)                                                                                  AS rosn_var
+
+        -- ==================== ROVN 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS rovn
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                                    AS rovn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                                     AS rovn_copc
+        ,ROUND(AVG(ABS(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT))), 6)            AS rovn_mae
+        ,ROUND(VARIANCE(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT)), 6)        AS rovn_var
+        ,ROUND(AVG(CAST(sortscore AS DOUBLE)), 6)                                               AS sortscore_avg
+
+        -- ==================== B链 ====================
+        ,SUM(CAST(bn_exp AS BIGINT))                                                    AS bn_exp
+        ,SUM(CAST(bn_pv AS BIGINT))                                                     AS bn_pv
+        ,SUM(CAST(bn_uv AS BIGINT))                                                     AS bn_uv
+        ,SUM(CAST(b1_exp AS BIGINT))                                                    AS b1_exp
+        ,SUM(CAST(b1_pv AS BIGINT))                                                     AS b1_pv
+        ,SUM(CAST(b1_uv AS BIGINT))                                                     AS b1_uv
+        ,SUM(CAST(b2_exp AS BIGINT))                                                    AS b2_exp
+        ,SUM(CAST(b2_pv AS BIGINT))                                                     AS b2_pv
+        ,SUM(CAST(b2_uv AS BIGINT))                                                     AS b2_uv
+        ,SUM(CAST(b3_exp AS BIGINT))                                                    AS b3_exp
+        ,SUM(CAST(b3_pv AS BIGINT))                                                     AS b3_pv
+        ,SUM(CAST(b3_uv AS BIGINT))                                                     AS b3_uv
+
+        -- ==================== C链 (全量depth, 按hop) ====================
+        ,SUM(CAST(cn_1_exp AS BIGINT))                                                  AS cn_1_exp
+        ,SUM(CAST(cn_1_pv AS BIGINT))                                                   AS cn_1_pv
+        ,SUM(CAST(cn_1_uv AS BIGINT))                                                   AS cn_1_uv
+        ,SUM(CAST(cn_2_exp AS BIGINT))                                                  AS cn_2_exp
+        ,SUM(CAST(cn_2_pv AS BIGINT))                                                   AS cn_2_pv
+        ,SUM(CAST(cn_2_uv AS BIGINT))                                                   AS cn_2_uv
+        ,SUM(CAST(cn_3_exp AS BIGINT))                                                  AS cn_3_exp
+        ,SUM(CAST(cn_3_pv AS BIGINT))                                                   AS cn_3_pv
+        ,SUM(CAST(cn_3_uv AS BIGINT))                                                   AS cn_3_uv
+        ,SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))  AS cn_total_uv
+
+        -- ==================== D链 (全量depth, 按hop) ====================
+        ,SUM(CAST(d0 AS BIGINT))                                                        AS d0
+        ,SUM(CAST(dn_1_exp AS BIGINT))                                                  AS dn_1_exp
+        ,SUM(CAST(dn_1_pv AS BIGINT))                                                   AS dn_1_pv
+        ,SUM(CAST(dn_1_uv AS BIGINT))                                                   AS dn_1_uv
+        ,SUM(CAST(dn_2_exp AS BIGINT))                                                  AS dn_2_exp
+        ,SUM(CAST(dn_2_pv AS BIGINT))                                                   AS dn_2_pv
+        ,SUM(CAST(dn_2_uv AS BIGINT))                                                   AS dn_2_uv
+        ,SUM(CAST(dn_3_exp AS BIGINT))                                                  AS dn_3_exp
+        ,SUM(CAST(dn_3_pv AS BIGINT))                                                   AS dn_3_pv
+        ,SUM(CAST(dn_3_uv AS BIGINT))                                                   AS dn_3_uv
+        ,SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))  AS dn_total_uv
+
+        -- ==================== 全链路 ====================
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))
+            + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+            + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+                                                                                        AS all_return_n_uv
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(COUNT(1), 0)
+        , 0), 6)                                                                        AS all_rovn
+
+
+-- =====================================================================
+-- FROM + GROUP BY CUBE
+-- =====================================================================
+
+FROM    t_wide
+
+GROUP BY CUBE(
+            user_type
+            ,hh_bucket
+            ,head_merge_leve2
+            ,vid_merge_leve2
+        )
+
+ORDER BY exposure_cnt DESC
+limit 1000
+;

+ 300 - 0
table_gen/test_2.sql

@@ -0,0 +1,300 @@
+WITH
+-- 用户拉活量分层
+t_user_type AS (
+    SELECT  DISTINCT type, openid
+    FROM    loghubods.mid_share_return_people_1year
+    WHERE   dt = TO_CHAR(DATEADD(TO_DATE('${dt}','YYYYMMDD'),-1,'dd'),'YYYYMMDD')
+    AND     type IS NOT NULL
+    AND     type != 'S_ALL'
+    AND     type NOT REGEXP 'R50'
+)
+-- 模型预估分数
+,t_score AS (
+    SELECT  apptype
+            ,videoid
+            ,recommendtraceid
+            ,scoresmap
+            ,sortscore
+    FROM    (
+                SELECT  apptype
+                        ,videoid
+                        ,recommendtraceid
+                        ,scoresmap
+                        ,sortscore
+                        ,ROW_NUMBER() OVER (PARTITION BY apptype,videoid,recommendtraceid) AS rn
+                FROM    loghubods.statistics_log_hour
+                WHERE   dt LIKE '${dt}%'
+                AND     scoresmap IS NOT NULL
+            )
+    WHERE   rn = 1
+)
+-- TOP1 进入内容品类(场): 按回流人数取 TOP1
+,t_top_head_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.headvideoid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY SUM(CAST(is_return_noself AS BIGINT)) DESC
+    LIMIT   1
+)
+-- TOP10 推荐内容品类(货): 按曝光次数取 TOP10
+,t_top_vid_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY COUNT(1) DESC
+    LIMIT   10
+)
+-- TOP1 内容id(货): 每品类按曝光次数取 TOP1 (曝光>10w)
+,t_top_vid AS (
+    SELECT  merge_leve2, vid
+    FROM    (
+                SELECT  vt.merge_leve2
+                        ,base.vid
+                        ,COUNT(1)                                                               AS exp_cnt
+                        ,ROW_NUMBER() OVER (PARTITION BY vt.merge_leve2 ORDER BY COUNT(1) DESC) AS rk
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+                JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+                WHERE   base.dt = '${dt}'
+                AND     vt.merge_leve2 IS NOT NULL
+                GROUP BY vt.merge_leve2, base.vid
+                HAVING  exp_cnt > 100000
+            )
+    WHERE   rk <= 1
+)
+-- 宽表
+,t_wide AS (
+    SELECT  base.*
+            ,CASE WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                  WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                  WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                  ELSE e.type
+             END AS user_type
+            ,CASE WHEN th.merge_leve2 IS NOT NULL THEN vt_head.merge_leve2 ELSE '其他' END AS head_merge_leve2
+            ,CASE WHEN tv.merge_leve2 IS NOT NULL THEN vt_vid.merge_leve2  ELSE '其他' END AS vid_merge_leve2
+            ,CASE WHEN ti.vid IS NOT NULL          THEN base.vid           ELSE '其他' END AS vid_id
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.fmRov') AS DOUBLE) AS str_pred
+            ,1.22*POW(CAST(GET_JSON_OBJECT(e1.scoresmap,'$.NorXGBScore') AS DOUBLE),1.15) AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.hasReturnRovScore') AS DOUBLE) AS rosn_pred_origin
+            ,e1.sortscore
+            ,CASE
+                WHEN CAST(hh AS INT) BETWEEN 0  AND 3  THEN '00-03'
+                WHEN CAST(hh AS INT) BETWEEN 4  AND 7  THEN '04-07'
+                WHEN CAST(hh AS INT) BETWEEN 8  AND 11 THEN '08-11'
+                WHEN CAST(hh AS INT) BETWEEN 12 AND 15 THEN '12-15'
+                WHEN CAST(hh AS INT) BETWEEN 16 AND 19 THEN '16-19'
+                WHEN CAST(hh AS INT) BETWEEN 20 AND 23 THEN '20-23'
+                ELSE '-'
+             END AS hh_bucket
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    LEFT JOIN t_user_type e
+    ON      SUBSTRING_INDEX(base.mid,'weixin_openid_',-1) = e.openid
+    LEFT JOIN loghubods.video_merge_tag vt_head
+    ON      base.headvideoid = vt_head.videoid
+    LEFT JOIN loghubods.video_merge_tag vt_vid
+    ON      base.vid = vt_vid.videoid
+    LEFT JOIN t_score e1
+    ON      base.apptype = e1.apptype
+    AND     base.vid = e1.videoid
+    AND     base.recomtraceid = e1.recommendtraceid
+    LEFT JOIN t_top_head_cate th
+    ON      vt_head.merge_leve2 = th.merge_leve2
+    LEFT JOIN t_top_vid_cate tv
+    ON      vt_vid.merge_leve2 = tv.merge_leve2
+    LEFT JOIN t_top_vid ti
+    ON      base.vid = ti.vid
+    WHERE   base.dt = '${dt}'
+)
+
+SELECT
+        -- ==================== 维度列 ====================
+        '${dt}'                                                                                     AS dt
+        ,CASE WHEN GROUPING(user_type) = 1 THEN 'SUM' ELSE NVL(user_type, 'SUM') END              AS user_type
+        ,CASE WHEN GROUPING(hh_bucket) = 1 THEN 'SUM' ELSE NVL(hh_bucket, 'SUM') END              AS hh_bucket
+        ,CASE WHEN GROUPING(head_merge_leve2) = 1 THEN 'SUM' ELSE NVL(head_merge_leve2, 'SUM') END AS head_merge_leve2
+        ,CASE WHEN GROUPING(vid_merge_leve2) = 1 THEN 'SUM' ELSE NVL(vid_merge_leve2, 'SUM') END   AS vid_merge_leve2
+        ,CASE WHEN GROUPING(vid_id) = 1 THEN 'SUM' ELSE NVL(vid_id, 'SUM') END                     AS vid_id
+
+        -- ==================== 基础流量 ====================
+        ,COUNT(1)                                                                       AS exposure_cnt
+        ,COUNT(DISTINCT mid)                                                            AS exposure_uv
+        ,COUNT(DISTINCT vid)                                                            AS vid_cnt
+        ,ROUND(COUNT(1) / COUNT(DISTINCT mid), 4)                                      AS exposure_per_user
+
+        -- ==================== 分享 ====================
+        ,SUM(CAST(is_share AS BIGINT))                                                  AS share_exposure_cnt
+        ,SUM(CAST(share_cnt AS BIGINT))                                                 AS share_cnt
+
+        -- ==================== STR 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS str_real
+        ,ROUND(COALESCE(SUM(str_pred) / NULLIF(COUNT(1), 0), 0), 6)                          AS str_pred
+        ,ROUND(
+            (SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(SUM(str_pred) / NULLIF(COUNT(1), 0), 0)
+        , 4)                                                                                   AS str_copc
+        ,ROUND(AVG(ABS(str_pred - CAST(is_return_noself AS BIGINT))), 6)                      AS str_mae
+        ,ROUND(VARIANCE(str_pred - CAST(is_return_noself AS BIGINT)), 6)                      AS str_var
+
+        -- ==================== ROSN 指标 ====================
+        ,ROUND(COALESCE(
+            SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0)
+        , 0), 6)                                                                               AS rosn_real
+        ,ROUND(COALESCE(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0), 6)  AS rosn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0))
+            / NULLIF(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0)
+        , 4)                                                                                   AS rosn_copc
+        ,ROUND(AVG(rosn_pred_origin), 6)                                                      AS rosn_pred_origin
+        ,ROUND(AVG(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN ABS(rosn_pred - CAST(return_n_uv_noself AS BIGINT))
+            END
+        ), 6)                                                                                  AS rosn_mae
+        ,ROUND(VARIANCE(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN rosn_pred - CAST(return_n_uv_noself AS BIGINT)
+            END
+        ), 6)                                                                                  AS rosn_var
+
+        -- ==================== ROVN 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS rovn
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                                    AS rovn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                                     AS rovn_copc
+        ,ROUND(AVG(ABS(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT))), 6)            AS rovn_mae
+        ,ROUND(VARIANCE(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT)), 6)        AS rovn_var
+        ,ROUND(AVG(CAST(sortscore AS DOUBLE)), 6)                                               AS sortscore_avg
+
+        -- ==================== B链 ====================
+        ,SUM(CAST(bn_exp AS BIGINT))                                                    AS bn_exp
+        ,SUM(CAST(bn_pv AS BIGINT))                                                     AS bn_pv
+        ,SUM(CAST(bn_uv AS BIGINT))                                                     AS bn_uv
+        ,SUM(CAST(b1_exp AS BIGINT))                                                    AS b1_exp
+        ,SUM(CAST(b1_pv AS BIGINT))                                                     AS b1_pv
+        ,SUM(CAST(b1_uv AS BIGINT))                                                     AS b1_uv
+        ,SUM(CAST(b2_exp AS BIGINT))                                                    AS b2_exp
+        ,SUM(CAST(b2_pv AS BIGINT))                                                     AS b2_pv
+        ,SUM(CAST(b2_uv AS BIGINT))                                                     AS b2_uv
+        ,SUM(CAST(b3_exp AS BIGINT))                                                    AS b3_exp
+        ,SUM(CAST(b3_pv AS BIGINT))                                                     AS b3_pv
+        ,SUM(CAST(b3_uv AS BIGINT))                                                     AS b3_uv
+
+        -- ==================== C链 (全量depth, 按hop) ====================
+        ,SUM(CAST(cn_1_exp AS BIGINT))                                                  AS cn_1_exp
+        ,SUM(CAST(cn_1_pv AS BIGINT))                                                   AS cn_1_pv
+        ,SUM(CAST(cn_1_uv AS BIGINT))                                                   AS cn_1_uv
+        ,SUM(CAST(cn_2_exp AS BIGINT))                                                  AS cn_2_exp
+        ,SUM(CAST(cn_2_pv AS BIGINT))                                                   AS cn_2_pv
+        ,SUM(CAST(cn_2_uv AS BIGINT))                                                   AS cn_2_uv
+        ,SUM(CAST(cn_3_exp AS BIGINT))                                                  AS cn_3_exp
+        ,SUM(CAST(cn_3_pv AS BIGINT))                                                   AS cn_3_pv
+        ,SUM(CAST(cn_3_uv AS BIGINT))                                                   AS cn_3_uv
+        ,SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))  AS cn_total_uv
+
+        -- ==================== C链 (按depth拆分) ====================
+        ,SUM(CAST(c1_1_exp AS BIGINT))                                                    AS c1_1_exp
+        ,SUM(CAST(c1_1_pv AS BIGINT))                                                     AS c1_1_pv
+        ,SUM(CAST(c1_1_uv AS BIGINT))                                                     AS c1_1_uv
+        ,SUM(CAST(c1_2_exp AS BIGINT))                                                    AS c1_2_exp
+        ,SUM(CAST(c1_2_pv AS BIGINT))                                                     AS c1_2_pv
+        ,SUM(CAST(c1_2_uv AS BIGINT))                                                     AS c1_2_uv
+        ,SUM(CAST(c1_3_exp AS BIGINT))                                                    AS c1_3_exp
+        ,SUM(CAST(c1_3_pv AS BIGINT))                                                     AS c1_3_pv
+        ,SUM(CAST(c1_3_uv AS BIGINT))                                                     AS c1_3_uv
+        ,SUM(CAST(c2_1_exp AS BIGINT))                                                    AS c2_1_exp
+        ,SUM(CAST(c2_1_pv AS BIGINT))                                                     AS c2_1_pv
+        ,SUM(CAST(c2_1_uv AS BIGINT))                                                     AS c2_1_uv
+        ,SUM(CAST(c2_2_exp AS BIGINT))                                                    AS c2_2_exp
+        ,SUM(CAST(c2_2_pv AS BIGINT))                                                     AS c2_2_pv
+        ,SUM(CAST(c2_2_uv AS BIGINT))                                                     AS c2_2_uv
+        ,SUM(CAST(c2_3_exp AS BIGINT))                                                    AS c2_3_exp
+        ,SUM(CAST(c2_3_pv AS BIGINT))                                                     AS c2_3_pv
+        ,SUM(CAST(c2_3_uv AS BIGINT))                                                     AS c2_3_uv
+        ,SUM(CAST(c3_1_exp AS BIGINT))                                                    AS c3_1_exp
+        ,SUM(CAST(c3_1_pv AS BIGINT))                                                     AS c3_1_pv
+        ,SUM(CAST(c3_1_uv AS BIGINT))                                                     AS c3_1_uv
+        ,SUM(CAST(c3_2_exp AS BIGINT))                                                    AS c3_2_exp
+        ,SUM(CAST(c3_2_pv AS BIGINT))                                                     AS c3_2_pv
+        ,SUM(CAST(c3_2_uv AS BIGINT))                                                     AS c3_2_uv
+        ,SUM(CAST(c3_3_exp AS BIGINT))                                                    AS c3_3_exp
+        ,SUM(CAST(c3_3_pv AS BIGINT))                                                     AS c3_3_pv
+        ,SUM(CAST(c3_3_uv AS BIGINT))                                                     AS c3_3_uv
+
+        -- ==================== D链 (全量depth, 按hop) ====================
+        ,SUM(CAST(d0 AS BIGINT))                                                        AS d0
+        ,SUM(CAST(dn_1_exp AS BIGINT))                                                  AS dn_1_exp
+        ,SUM(CAST(dn_1_pv AS BIGINT))                                                   AS dn_1_pv
+        ,SUM(CAST(dn_1_uv AS BIGINT))                                                   AS dn_1_uv
+        ,SUM(CAST(dn_2_exp AS BIGINT))                                                  AS dn_2_exp
+        ,SUM(CAST(dn_2_pv AS BIGINT))                                                   AS dn_2_pv
+        ,SUM(CAST(dn_2_uv AS BIGINT))                                                   AS dn_2_uv
+        ,SUM(CAST(dn_3_exp AS BIGINT))                                                  AS dn_3_exp
+        ,SUM(CAST(dn_3_pv AS BIGINT))                                                   AS dn_3_pv
+        ,SUM(CAST(dn_3_uv AS BIGINT))                                                   AS dn_3_uv
+        ,SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))  AS dn_total_uv
+
+        -- ==================== D链 (按depth拆分) ====================
+        ,SUM(CAST(d1_1_exp AS BIGINT))                                                    AS d1_1_exp
+        ,SUM(CAST(d1_1_pv AS BIGINT))                                                     AS d1_1_pv
+        ,SUM(CAST(d1_1_uv AS BIGINT))                                                     AS d1_1_uv
+        ,SUM(CAST(d1_2_exp AS BIGINT))                                                    AS d1_2_exp
+        ,SUM(CAST(d1_2_pv AS BIGINT))                                                     AS d1_2_pv
+        ,SUM(CAST(d1_2_uv AS BIGINT))                                                     AS d1_2_uv
+        ,SUM(CAST(d1_3_exp AS BIGINT))                                                    AS d1_3_exp
+        ,SUM(CAST(d1_3_pv AS BIGINT))                                                     AS d1_3_pv
+        ,SUM(CAST(d1_3_uv AS BIGINT))                                                     AS d1_3_uv
+        ,SUM(CAST(d2_1_exp AS BIGINT))                                                    AS d2_1_exp
+        ,SUM(CAST(d2_1_pv AS BIGINT))                                                     AS d2_1_pv
+        ,SUM(CAST(d2_1_uv AS BIGINT))                                                     AS d2_1_uv
+        ,SUM(CAST(d2_2_exp AS BIGINT))                                                    AS d2_2_exp
+        ,SUM(CAST(d2_2_pv AS BIGINT))                                                     AS d2_2_pv
+        ,SUM(CAST(d2_2_uv AS BIGINT))                                                     AS d2_2_uv
+        ,SUM(CAST(d2_3_exp AS BIGINT))                                                    AS d2_3_exp
+        ,SUM(CAST(d2_3_pv AS BIGINT))                                                     AS d2_3_pv
+        ,SUM(CAST(d2_3_uv AS BIGINT))                                                     AS d2_3_uv
+        ,SUM(CAST(d3_1_exp AS BIGINT))                                                    AS d3_1_exp
+        ,SUM(CAST(d3_1_pv AS BIGINT))                                                     AS d3_1_pv
+        ,SUM(CAST(d3_1_uv AS BIGINT))                                                     AS d3_1_uv
+        ,SUM(CAST(d3_2_exp AS BIGINT))                                                    AS d3_2_exp
+        ,SUM(CAST(d3_2_pv AS BIGINT))                                                     AS d3_2_pv
+        ,SUM(CAST(d3_2_uv AS BIGINT))                                                     AS d3_2_uv
+        ,SUM(CAST(d3_3_exp AS BIGINT))                                                    AS d3_3_exp
+        ,SUM(CAST(d3_3_pv AS BIGINT))                                                     AS d3_3_pv
+        ,SUM(CAST(d3_3_uv AS BIGINT))                                                     AS d3_3_uv
+
+        -- ==================== 全链路 ====================
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))
+            + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+            + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+                                                                                        AS all_return_n_uv
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(COUNT(1), 0)
+        , 0), 6)                                                                        AS all_rovn
+
+
+-- =====================================================================
+-- FROM + GROUP BY CUBE
+-- =====================================================================
+
+FROM    t_wide
+
+GROUP BY CUBE(
+            user_type
+            ,hh_bucket
+            ,head_merge_leve2
+            ,vid_merge_leve2
+            ,vid_id
+        )
+
+ORDER BY exposure_cnt DESC
+;

+ 601 - 0
table_gen/test_3.sql

@@ -0,0 +1,601 @@
+-- =====================================================================
+-- 曝光回流链路 CUBE 聚合表 (基于 wide 宽表, 增加用户/品类维度 + 模型预估指标)
+-- 维度: user_type × hh_bucket × head_merge_leve2 × vid_merge_leve2 × vid_id (CUBE)
+-- 参考: de.sql + dwd_recsys_alg_exposure_agg_20260209
+-- =====================================================================
+
+-- -- DROP TABLE IF EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209;
+-- CREATE TABLE IF NOT EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209 (
+--     -- ==================== 维度列 ====================
+--     dt                         STRING    COMMENT '日期'
+--     ,user_type                  STRING    COMMENT '用户拉活量分层(R0&新用户/R1-50/R_180_330等,汇总为SUM)'
+--     ,hh_bucket                STRING    COMMENT '小时段(00-03/04-07/.../20-23,汇总为SUM)'
+--     ,head_merge_leve2         STRING    COMMENT '进入内容品类(headvideoid品类,汇总为SUM)'
+--     ,vid_merge_leve2          STRING    COMMENT '推荐内容品类(vid品类,TOP10曝光+其他,汇总为SUM)'
+--     ,vid_id                   STRING    COMMENT '内容id(品类曝光TOP1+其他,汇总为SUM)'
+
+--     -- ==================== 基础流量 ====================
+--     ,exposure_cnt             BIGINT    COMMENT '曝光次数'
+--     ,exposure_uv              BIGINT    COMMENT '曝光人数(mid去重)'
+--     ,vid_cnt                  BIGINT    COMMENT '视频个数(vid去重)'
+--     ,exposure_per_user        DOUBLE    COMMENT '人均曝光次数 = 曝光次数/曝光人数'
+
+--     -- ==================== 分享 ====================
+--     ,share_exposure_cnt       BIGINT    COMMENT '产生分享的曝光数'
+--     ,share_cnt                BIGINT    COMMENT '分享总次数'
+
+--     -- ==================== STR 指标 ====================
+--     ,str_real                 DOUBLE    COMMENT 'STR实际 = is_return_noself/曝光次数'
+--     ,str_pred                 DOUBLE    COMMENT 'STR预估 = SUM(str_pred)/曝光次数'
+--     ,str_copc                 DOUBLE    COMMENT 'STR copc = str_real/str_pred'
+--     ,str_mae                  DOUBLE    COMMENT 'STR MAE = AVG(ABS(str_pred - is_return_noself))'
+--     ,str_var                  DOUBLE    COMMENT 'STR VAR = VARIANCE(str_pred - is_return_noself)'
+
+--     -- ==================== ROSN 指标 ====================
+--     ,rosn_real                DOUBLE    COMMENT 'ROSN实际 = return_n_uv_noself/is_return_noself'
+--     ,rosn_pred                DOUBLE    COMMENT 'ROSN预估 = SUM(rosn_pred)/is_return_noself'
+--     ,rosn_copc                DOUBLE    COMMENT 'ROSN copc = rosn_real/rosn_pred'
+--     ,rosn_pred_origin         DOUBLE    COMMENT 'ROSN原始预估均值 = AVG(rosn_pred_origin)'
+--     ,rosn_mae                 DOUBLE    COMMENT 'ROSN MAE = AVG(ABS(rosn_pred - return_n_uv_noself)) WHERE is_return_noself=1'
+--     ,rosn_var                 DOUBLE    COMMENT 'ROSN VAR = VARIANCE(rosn_pred - return_n_uv_noself) WHERE is_return_noself=1'
+
+--     -- ==================== ROVN 指标 ====================
+--     ,rovn                     DOUBLE    COMMENT 'rovn实际 = return_n_uv_noself/曝光次数'
+--     ,rovn_pred                DOUBLE    COMMENT 'rovn预估 = AVG(str_pred*rosn_pred)'
+--     ,rovn_copc                DOUBLE    COMMENT 'rovn copc = rovn/rovn_pred'
+--     ,rovn_mae                 DOUBLE    COMMENT 'rovn MAE = AVG(ABS(str_pred*rosn_pred - return_n_uv_noself/曝光次数))'
+--     ,rovn_var                 DOUBLE    COMMENT 'rovn VAR = VARIANCE(str_pred*rosn_pred - return_n_uv_noself/曝光次数)'
+--     ,sortscore_avg            DOUBLE    COMMENT 'sortscore均值'
+
+--     -- ==================== B链 (分享→点击) ====================
+--     ,bn_exp                   BIGINT    COMMENT 'B链全量: 回流session曝光数'
+--     ,bn_pv                    BIGINT    COMMENT 'B链全量: 回流点击次数'
+--     ,bn_uv                    BIGINT    COMMENT 'B链全量: 回流去重人数'
+--     ,b1_exp                   BIGINT    COMMENT 'B链depth=1: 回流session曝光数'
+--     ,b1_pv                    BIGINT    COMMENT 'B链depth=1: 回流点击次数'
+--     ,b1_uv                    BIGINT    COMMENT 'B链depth=1: 回流去重人数'
+--     ,b2_exp                   BIGINT    COMMENT 'B链depth=2: 回流session曝光数'
+--     ,b2_pv                    BIGINT    COMMENT 'B链depth=2: 回流点击次数'
+--     ,b2_uv                    BIGINT    COMMENT 'B链depth=2: 回流去重人数'
+--     ,b3_exp                   BIGINT    COMMENT 'B链depth=3: 回流session曝光数'
+--     ,b3_pv                    BIGINT    COMMENT 'B链depth=3: 回流点击次数'
+--     ,b3_uv                    BIGINT    COMMENT 'B链depth=3: 回流去重人数'
+--     ,bn_rov                   DOUBLE    COMMENT 'B链全量: rov = bn_uv/曝光次数'
+--     ,bn_ror                   DOUBLE    COMMENT 'B链全量: ror = bn_uv/曝光人数'
+--     ,b1_rov                   DOUBLE    COMMENT 'B链depth=1: rov = b1_uv/曝光次数'
+--     ,b1_ror                   DOUBLE    COMMENT 'B链depth=1: ror = b1_uv/曝光人数'
+--     ,b2_rov                   DOUBLE    COMMENT 'B链depth=2: rov = b2_uv/b1曝光数'
+--     ,b2_ror                   DOUBLE    COMMENT 'B链depth=2: ror = b2_uv/b1人数'
+--     ,b3_rov                   DOUBLE    COMMENT 'B链depth=3: rov = b3_uv/b2曝光数'
+--     ,b3_ror                   DOUBLE    COMMENT 'B链depth=3: ror = b3_uv/b2人数'
+
+--     -- ==================== C链 (全量depth, 按hop) ====================
+--     ,cn_1_exp                 BIGINT    COMMENT 'C链hop1: 回流session曝光数'
+--     ,cn_1_pv                  BIGINT    COMMENT 'C链hop1: 回流点击次数'
+--     ,cn_1_uv                  BIGINT    COMMENT 'C链hop1: 回流去重人数'
+--     ,cn_2_exp                 BIGINT    COMMENT 'C链hop2: 回流session曝光数'
+--     ,cn_2_pv                  BIGINT    COMMENT 'C链hop2: 回流点击次数'
+--     ,cn_2_uv                  BIGINT    COMMENT 'C链hop2: 回流去重人数'
+--     ,cn_3_exp                 BIGINT    COMMENT 'C链hop3: 回流session曝光数'
+--     ,cn_3_pv                  BIGINT    COMMENT 'C链hop3: 回流点击次数'
+--     ,cn_3_uv                  BIGINT    COMMENT 'C链hop3: 回流去重人数'
+--     ,cn_total_uv              BIGINT    COMMENT 'C链合计UV'
+--     ,cn_1_rov                 DOUBLE    COMMENT 'C链hop1: rov = cn_1_uv/bn曝光数'
+--     ,cn_1_ror                 DOUBLE    COMMENT 'C链hop1: ror = cn_1_uv/bn人数'
+--     ,cn_2_rov                 DOUBLE    COMMENT 'C链hop2: rov = cn_2_uv/cn_1曝光数'
+--     ,cn_2_ror                 DOUBLE    COMMENT 'C链hop2: ror = cn_2_uv/cn_1人数'
+--     ,cn_3_rov                 DOUBLE    COMMENT 'C链hop3: rov = cn_3_uv/cn_2曝光数'
+--     ,cn_3_ror                 DOUBLE    COMMENT 'C链hop3: ror = cn_3_uv/cn_2人数'
+--     ,cn_total_rov             DOUBLE    COMMENT 'C链合计: rov = cn_total_uv/bn曝光数'
+--     ,cn_total_ror             DOUBLE    COMMENT 'C链合计: ror = cn_total_uv/bn人数'
+--     ,c1_1_exp                 BIGINT    COMMENT 'C链depth1-hop1: 回流session曝光数'
+--     ,c1_1_pv                  BIGINT    COMMENT 'C链depth1-hop1: 回流点击次数'
+--     ,c1_1_uv                  BIGINT    COMMENT 'C链depth1-hop1: 回流去重人数'
+--     ,c1_2_exp                 BIGINT    COMMENT 'C链depth1-hop2: 回流session曝光数'
+--     ,c1_2_pv                  BIGINT    COMMENT 'C链depth1-hop2: 回流点击次数'
+--     ,c1_2_uv                  BIGINT    COMMENT 'C链depth1-hop2: 回流去重人数'
+--     ,c1_3_exp                 BIGINT    COMMENT 'C链depth1-hop3: 回流session曝光数'
+--     ,c1_3_pv                  BIGINT    COMMENT 'C链depth1-hop3: 回流点击次数'
+--     ,c1_3_uv                  BIGINT    COMMENT 'C链depth1-hop3: 回流去重人数'
+--     ,c2_1_exp                 BIGINT    COMMENT 'C链depth2-hop1: 回流session曝光数'
+--     ,c2_1_pv                  BIGINT    COMMENT 'C链depth2-hop1: 回流点击次数'
+--     ,c2_1_uv                  BIGINT    COMMENT 'C链depth2-hop1: 回流去重人数'
+--     ,c2_2_exp                 BIGINT    COMMENT 'C链depth2-hop2: 回流session曝光数'
+--     ,c2_2_pv                  BIGINT    COMMENT 'C链depth2-hop2: 回流点击次数'
+--     ,c2_2_uv                  BIGINT    COMMENT 'C链depth2-hop2: 回流去重人数'
+--     ,c2_3_exp                 BIGINT    COMMENT 'C链depth2-hop3: 回流session曝光数'
+--     ,c2_3_pv                  BIGINT    COMMENT 'C链depth2-hop3: 回流点击次数'
+--     ,c2_3_uv                  BIGINT    COMMENT 'C链depth2-hop3: 回流去重人数'
+--     ,c3_1_exp                 BIGINT    COMMENT 'C链depth3-hop1: 回流session曝光数'
+--     ,c3_1_pv                  BIGINT    COMMENT 'C链depth3-hop1: 回流点击次数'
+--     ,c3_1_uv                  BIGINT    COMMENT 'C链depth3-hop1: 回流去重人数'
+--     ,c3_2_exp                 BIGINT    COMMENT 'C链depth3-hop2: 回流session曝光数'
+--     ,c3_2_pv                  BIGINT    COMMENT 'C链depth3-hop2: 回流点击次数'
+--     ,c3_2_uv                  BIGINT    COMMENT 'C链depth3-hop2: 回流去重人数'
+--     ,c3_3_exp                 BIGINT    COMMENT 'C链depth3-hop3: 回流session曝光数'
+--     ,c3_3_pv                  BIGINT    COMMENT 'C链depth3-hop3: 回流点击次数'
+--     ,c3_3_uv                  BIGINT    COMMENT 'C链depth3-hop3: 回流去重人数'
+--     ,c1_1_rov                 DOUBLE    COMMENT 'C链d1-hop1: rov = c1_1_uv/bn曝光数'
+--     ,c1_1_ror                 DOUBLE    COMMENT 'C链d1-hop1: ror = c1_1_uv/bn人数'
+--     ,c2_1_rov                 DOUBLE    COMMENT 'C链d2-hop1: rov = c2_1_uv/c1_1曝光数'
+--     ,c2_1_ror                 DOUBLE    COMMENT 'C链d2-hop1: ror = c2_1_uv/c1_1人数'
+--     ,c3_1_rov                 DOUBLE    COMMENT 'C链d3-hop1: rov = c3_1_uv/c2_1曝光数'
+--     ,c3_1_ror                 DOUBLE    COMMENT 'C链d3-hop1: ror = c3_1_uv/c2_1人数'
+--     ,c1_2_rov                 DOUBLE    COMMENT 'C链d1-hop2: rov = c1_2_uv/cn_1曝光数'
+--     ,c1_2_ror                 DOUBLE    COMMENT 'C链d1-hop2: ror = c1_2_uv/cn_1人数'
+--     ,c2_2_rov                 DOUBLE    COMMENT 'C链d2-hop2: rov = c2_2_uv/c1_2曝光数'
+--     ,c2_2_ror                 DOUBLE    COMMENT 'C链d2-hop2: ror = c2_2_uv/c1_2人数'
+--     ,c3_2_rov                 DOUBLE    COMMENT 'C链d3-hop2: rov = c3_2_uv/c2_2曝光数'
+--     ,c3_2_ror                 DOUBLE    COMMENT 'C链d3-hop2: ror = c3_2_uv/c2_2人数'
+--     ,c1_3_rov                 DOUBLE    COMMENT 'C链d1-hop3: rov = c1_3_uv/cn_2曝光数'
+--     ,c1_3_ror                 DOUBLE    COMMENT 'C链d1-hop3: ror = c1_3_uv/cn_2人数'
+--     ,c2_3_rov                 DOUBLE    COMMENT 'C链d2-hop3: rov = c2_3_uv/c1_3曝光数'
+--     ,c2_3_ror                 DOUBLE    COMMENT 'C链d2-hop3: ror = c2_3_uv/c1_3人数'
+--     ,c3_3_rov                 DOUBLE    COMMENT 'C链d3-hop3: rov = c3_3_uv/c2_3曝光数'
+--     ,c3_3_ror                 DOUBLE    COMMENT 'C链d3-hop3: ror = c3_3_uv/c2_3人数'
+
+--     -- ==================== D链 (session内后续曝光传播) ====================
+--     ,d0                       BIGINT    COMMENT 'D链初始成本: session内后续曝光数'
+--     ,dn_1_exp                 BIGINT    COMMENT 'D链hop1: 回流session曝光数'
+--     ,dn_1_pv                  BIGINT    COMMENT 'D链hop1: 回流点击次数'
+--     ,dn_1_uv                  BIGINT    COMMENT 'D链hop1: 回流去重人数'
+--     ,dn_2_exp                 BIGINT    COMMENT 'D链hop2: 回流session曝光数'
+--     ,dn_2_pv                  BIGINT    COMMENT 'D链hop2: 回流点击次数'
+--     ,dn_2_uv                  BIGINT    COMMENT 'D链hop2: 回流去重人数'
+--     ,dn_3_exp                 BIGINT    COMMENT 'D链hop3: 回流session曝光数'
+--     ,dn_3_pv                  BIGINT    COMMENT 'D链hop3: 回流点击次数'
+--     ,dn_3_uv                  BIGINT    COMMENT 'D链hop3: 回流去重人数'
+--     ,dn_total_uv              BIGINT    COMMENT 'D链合计UV'
+--     ,dn_1_rov                 DOUBLE    COMMENT 'D链hop1: rov = dn_1_uv/d0初始曝光数'
+--     ,dn_1_ror                 DOUBLE    COMMENT 'D链hop1: ror = dn_1_uv/曝光人数'
+--     ,dn_2_rov                 DOUBLE    COMMENT 'D链hop2: rov = dn_2_uv/dn_1曝光数'
+--     ,dn_2_ror                 DOUBLE    COMMENT 'D链hop2: ror = dn_2_uv/dn_1人数'
+--     ,dn_3_rov                 DOUBLE    COMMENT 'D链hop3: rov = dn_3_uv/dn_2曝光数'
+--     ,dn_3_ror                 DOUBLE    COMMENT 'D链hop3: ror = dn_3_uv/dn_2人数'
+--     ,dn_total_rov             DOUBLE    COMMENT 'D链合计: rov = dn_total_uv/d0初始曝光数'
+--     ,dn_total_ror             DOUBLE    COMMENT 'D链合计: ror = dn_total_uv/曝光人数'
+--     ,d1_1_exp                 BIGINT    COMMENT 'D链depth1-hop1: 回流session曝光数'
+--     ,d1_1_pv                  BIGINT    COMMENT 'D链depth1-hop1: 回流点击次数'
+--     ,d1_1_uv                  BIGINT    COMMENT 'D链depth1-hop1: 回流去重人数'
+--     ,d1_2_exp                 BIGINT    COMMENT 'D链depth1-hop2: 回流session曝光数'
+--     ,d1_2_pv                  BIGINT    COMMENT 'D链depth1-hop2: 回流点击次数'
+--     ,d1_2_uv                  BIGINT    COMMENT 'D链depth1-hop2: 回流去重人数'
+--     ,d1_3_exp                 BIGINT    COMMENT 'D链depth1-hop3: 回流session曝光数'
+--     ,d1_3_pv                  BIGINT    COMMENT 'D链depth1-hop3: 回流点击次数'
+--     ,d1_3_uv                  BIGINT    COMMENT 'D链depth1-hop3: 回流去重人数'
+--     ,d2_1_exp                 BIGINT    COMMENT 'D链depth2-hop1: 回流session曝光数'
+--     ,d2_1_pv                  BIGINT    COMMENT 'D链depth2-hop1: 回流点击次数'
+--     ,d2_1_uv                  BIGINT    COMMENT 'D链depth2-hop1: 回流去重人数'
+--     ,d2_2_exp                 BIGINT    COMMENT 'D链depth2-hop2: 回流session曝光数'
+--     ,d2_2_pv                  BIGINT    COMMENT 'D链depth2-hop2: 回流点击次数'
+--     ,d2_2_uv                  BIGINT    COMMENT 'D链depth2-hop2: 回流去重人数'
+--     ,d2_3_exp                 BIGINT    COMMENT 'D链depth2-hop3: 回流session曝光数'
+--     ,d2_3_pv                  BIGINT    COMMENT 'D链depth2-hop3: 回流点击次数'
+--     ,d2_3_uv                  BIGINT    COMMENT 'D链depth2-hop3: 回流去重人数'
+--     ,d3_1_exp                 BIGINT    COMMENT 'D链depth3-hop1: 回流session曝光数'
+--     ,d3_1_pv                  BIGINT    COMMENT 'D链depth3-hop1: 回流点击次数'
+--     ,d3_1_uv                  BIGINT    COMMENT 'D链depth3-hop1: 回流去重人数'
+--     ,d3_2_exp                 BIGINT    COMMENT 'D链depth3-hop2: 回流session曝光数'
+--     ,d3_2_pv                  BIGINT    COMMENT 'D链depth3-hop2: 回流点击次数'
+--     ,d3_2_uv                  BIGINT    COMMENT 'D链depth3-hop2: 回流去重人数'
+--     ,d3_3_exp                 BIGINT    COMMENT 'D链depth3-hop3: 回流session曝光数'
+--     ,d3_3_pv                  BIGINT    COMMENT 'D链depth3-hop3: 回流点击次数'
+--     ,d3_3_uv                  BIGINT    COMMENT 'D链depth3-hop3: 回流去重人数'
+--     ,d1_1_rov                 DOUBLE    COMMENT 'D链d1-hop1: rov = d1_1_uv/d0初始曝光数'
+--     ,d1_1_ror                 DOUBLE    COMMENT 'D链d1-hop1: ror = d1_1_uv/曝光人数'
+--     ,d2_1_rov                 DOUBLE    COMMENT 'D链d2-hop1: rov = d2_1_uv/d1_1曝光数'
+--     ,d2_1_ror                 DOUBLE    COMMENT 'D链d2-hop1: ror = d2_1_uv/d1_1人数'
+--     ,d3_1_rov                 DOUBLE    COMMENT 'D链d3-hop1: rov = d3_1_uv/d2_1曝光数'
+--     ,d3_1_ror                 DOUBLE    COMMENT 'D链d3-hop1: ror = d3_1_uv/d2_1人数'
+--     ,d1_2_rov                 DOUBLE    COMMENT 'D链d1-hop2: rov = d1_2_uv/dn_1曝光数'
+--     ,d1_2_ror                 DOUBLE    COMMENT 'D链d1-hop2: ror = d1_2_uv/dn_1人数'
+--     ,d2_2_rov                 DOUBLE    COMMENT 'D链d2-hop2: rov = d2_2_uv/d1_2曝光数'
+--     ,d2_2_ror                 DOUBLE    COMMENT 'D链d2-hop2: ror = d2_2_uv/d1_2人数'
+--     ,d3_2_rov                 DOUBLE    COMMENT 'D链d3-hop2: rov = d3_2_uv/d2_2曝光数'
+--     ,d3_2_ror                 DOUBLE    COMMENT 'D链d3-hop2: ror = d3_2_uv/d2_2人数'
+--     ,d1_3_rov                 DOUBLE    COMMENT 'D链d1-hop3: rov = d1_3_uv/dn_2曝光数'
+--     ,d1_3_ror                 DOUBLE    COMMENT 'D链d1-hop3: ror = d1_3_uv/dn_2人数'
+--     ,d2_3_rov                 DOUBLE    COMMENT 'D链d2-hop3: rov = d2_3_uv/d1_3曝光数'
+--     ,d2_3_ror                 DOUBLE    COMMENT 'D链d2-hop3: ror = d2_3_uv/d1_3人数'
+--     ,d3_3_rov                 DOUBLE    COMMENT 'D链d3-hop3: rov = d3_3_uv/d2_3曝光数'
+--     ,d3_3_ror                 DOUBLE    COMMENT 'D链d3-hop3: ror = d3_3_uv/d2_3人数'
+
+--     -- ==================== 全链路 ====================
+--     ,all_return_n_uv          BIGINT    COMMENT '全链路拉回UV = B + C + D'
+--     ,all_rovn                 DOUBLE    COMMENT '全链路拉回率 = all_return_n_uv/曝光次数'
+--     ,all_rov                  DOUBLE    COMMENT '全链路: rov = all_return_n_uv/曝光次数'
+--     ,all_ror                  DOUBLE    COMMENT '全链路: ror = all_return_n_uv/曝光人数'
+-- )
+-- COMMENT '曝光回流链路CUBE聚合-宽表版 (5维度: 用户分层/小时段/进入品类TOP1/推荐品类TOP10/内容idTOP1)'
+-- ;
+
+WITH
+-- 用户拉活量分层
+t_user_type AS (
+    SELECT  DISTINCT type, openid
+    FROM    loghubods.mid_share_return_people_1year
+    WHERE   dt = TO_CHAR(DATEADD(TO_DATE('${dt}','YYYYMMDD'),-1,'dd'),'YYYYMMDD')
+    AND     type IS NOT NULL
+    AND     type != 'S_ALL'
+    AND     type NOT REGEXP 'R50'
+)
+-- 模型预估分数
+,t_score AS (
+    SELECT  apptype
+            ,videoid
+            ,recommendtraceid
+            ,scoresmap
+            ,sortscore
+    FROM    (
+                SELECT  apptype
+                        ,videoid
+                        ,recommendtraceid
+                        ,scoresmap
+                        ,sortscore
+                        ,ROW_NUMBER() OVER (PARTITION BY apptype,videoid,recommendtraceid) AS rn
+                FROM    loghubods.statistics_log_hour
+                WHERE   dt LIKE '${dt}%'
+                AND     scoresmap IS NOT NULL
+            )
+    WHERE   rn = 1
+)
+-- TOP1 进入内容品类(场): 按回流人数取 TOP1
+,t_top_head_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.headvideoid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY SUM(CAST(is_return_noself AS BIGINT)) DESC
+    LIMIT   1
+)
+-- TOP10 推荐内容品类(货): 按曝光次数取 TOP10
+,t_top_vid_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY COUNT(1) DESC
+    LIMIT   10
+)
+-- TOP1 内容id(货): 每品类按曝光次数取 TOP1 (曝光>10w)
+,t_top_vid AS (
+    SELECT  merge_leve2, vid
+    FROM    (
+                SELECT  vt.merge_leve2
+                        ,base.vid
+                        ,COUNT(1)                                                               AS exp_cnt
+                        ,ROW_NUMBER() OVER (PARTITION BY vt.merge_leve2 ORDER BY COUNT(1) DESC) AS rk
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+                JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+                WHERE   base.dt = '${dt}'
+                AND     vt.merge_leve2 IS NOT NULL
+                GROUP BY vt.merge_leve2, base.vid
+                HAVING  exp_cnt > 100000
+            )
+    WHERE   rk <= 1
+)
+-- 宽表
+,t_wide AS (
+    SELECT  base.*
+            ,CASE WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                  WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                  WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                  ELSE e.type
+             END AS user_type
+            ,CASE WHEN th.merge_leve2 IS NOT NULL THEN vt_head.merge_leve2 ELSE '其他' END AS head_merge_leve2
+            ,CASE WHEN tv.merge_leve2 IS NOT NULL THEN vt_vid.merge_leve2  ELSE '其他' END AS vid_merge_leve2
+            ,CASE WHEN ti.vid IS NOT NULL          THEN base.vid           ELSE '其他' END AS vid_id
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.fmRov') AS DOUBLE) AS str_pred
+            ,1.22*POW(CAST(GET_JSON_OBJECT(e1.scoresmap,'$.NorXGBScore') AS DOUBLE),1.15) AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.hasReturnRovScore') AS DOUBLE) AS rosn_pred_origin
+            ,e1.sortscore
+            ,CASE
+                WHEN CAST(hh AS INT) BETWEEN 0  AND 3  THEN '00-03'
+                WHEN CAST(hh AS INT) BETWEEN 4  AND 7  THEN '04-07'
+                WHEN CAST(hh AS INT) BETWEEN 8  AND 11 THEN '08-11'
+                WHEN CAST(hh AS INT) BETWEEN 12 AND 15 THEN '12-15'
+                WHEN CAST(hh AS INT) BETWEEN 16 AND 19 THEN '16-19'
+                WHEN CAST(hh AS INT) BETWEEN 20 AND 23 THEN '20-23'
+                ELSE '-'
+             END AS hh_bucket
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    LEFT JOIN t_user_type e
+    ON      SUBSTRING_INDEX(base.mid,'weixin_openid_',-1) = e.openid
+    LEFT JOIN loghubods.video_merge_tag vt_head
+    ON      base.headvideoid = vt_head.videoid
+    LEFT JOIN loghubods.video_merge_tag vt_vid
+    ON      base.vid = vt_vid.videoid
+    LEFT JOIN t_score e1
+    ON      base.apptype = e1.apptype
+    AND     base.vid = e1.videoid
+    AND     base.recomtraceid = e1.recommendtraceid
+    LEFT JOIN t_top_head_cate th
+    ON      vt_head.merge_leve2 = th.merge_leve2
+    LEFT JOIN t_top_vid_cate tv
+    ON      vt_vid.merge_leve2 = tv.merge_leve2
+    LEFT JOIN t_top_vid ti
+    ON      base.vid = ti.vid
+    WHERE   base.dt = '${dt}'
+)
+
+SELECT
+        -- ==================== 维度列 ====================
+        '${dt}'                                                                                     AS dt
+        ,CASE WHEN GROUPING(user_type) = 1 THEN 'SUM' ELSE NVL(user_type, 'SUM') END              AS user_type
+        ,CASE WHEN GROUPING(hh_bucket) = 1 THEN 'SUM' ELSE NVL(hh_bucket, 'SUM') END              AS hh_bucket
+        ,CASE WHEN GROUPING(head_merge_leve2) = 1 THEN 'SUM' ELSE NVL(head_merge_leve2, 'SUM') END AS head_merge_leve2
+        ,CASE WHEN GROUPING(vid_merge_leve2) = 1 THEN 'SUM' ELSE NVL(vid_merge_leve2, 'SUM') END   AS vid_merge_leve2
+        ,CASE WHEN GROUPING(vid_id) = 1 THEN 'SUM' ELSE NVL(vid_id, 'SUM') END                     AS vid_id
+
+        -- ==================== 基础流量 ====================
+        ,COUNT(1)                                                                       AS exposure_cnt
+        ,COUNT(DISTINCT mid)                                                            AS exposure_uv
+        ,COUNT(DISTINCT vid)                                                            AS vid_cnt
+        ,ROUND(COUNT(1) / COUNT(DISTINCT mid), 4)                                      AS exposure_per_user
+
+        -- ==================== 分享 ====================
+        ,SUM(CAST(is_share AS BIGINT))                                                  AS share_exposure_cnt
+        ,SUM(CAST(share_cnt AS BIGINT))                                                 AS share_cnt
+
+        -- ==================== STR 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS str_real
+        ,ROUND(COALESCE(SUM(str_pred) / NULLIF(COUNT(1), 0), 0), 6)                          AS str_pred
+        ,ROUND(
+            (SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(SUM(str_pred) / NULLIF(COUNT(1), 0), 0)
+        , 4)                                                                                   AS str_copc
+        ,ROUND(AVG(ABS(str_pred - CAST(is_return_noself AS BIGINT))), 6)                      AS str_mae
+        ,ROUND(VARIANCE(str_pred - CAST(is_return_noself AS BIGINT)), 6)                      AS str_var
+
+        -- ==================== ROSN 指标 ====================
+        ,ROUND(COALESCE(
+            SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0)
+        , 0), 6)                                                                               AS rosn_real
+        ,ROUND(COALESCE(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0), 6)  AS rosn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0))
+            / NULLIF(SUM(rosn_pred) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0)
+        , 4)                                                                                   AS rosn_copc
+        ,ROUND(AVG(rosn_pred_origin), 6)                                                      AS rosn_pred_origin
+        ,ROUND(AVG(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN ABS(rosn_pred - CAST(return_n_uv_noself AS BIGINT))
+            END
+        ), 6)                                                                                  AS rosn_mae
+        ,ROUND(VARIANCE(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN rosn_pred - CAST(return_n_uv_noself AS BIGINT)
+            END
+        ), 6)                                                                                  AS rosn_var
+
+        -- ==================== ROVN 指标 ====================
+        ,ROUND(COALESCE(SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS rovn
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                                    AS rovn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                                     AS rovn_copc
+        ,ROUND(AVG(ABS(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT))), 6)            AS rovn_mae
+        ,ROUND(VARIANCE(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT)), 6)        AS rovn_var
+        ,ROUND(AVG(CAST(sortscore AS DOUBLE)), 6)                                               AS sortscore_avg
+
+        -- ==================== B链 ====================
+        ,SUM(CAST(bn_exp AS BIGINT))                                                    AS bn_exp
+        ,SUM(CAST(bn_pv AS BIGINT))                                                     AS bn_pv
+        ,SUM(CAST(bn_uv AS BIGINT))                                                     AS bn_uv
+        ,SUM(CAST(b1_exp AS BIGINT))                                                    AS b1_exp
+        ,SUM(CAST(b1_pv AS BIGINT))                                                     AS b1_pv
+        ,SUM(CAST(b1_uv AS BIGINT))                                                     AS b1_uv
+        ,SUM(CAST(b2_exp AS BIGINT))                                                    AS b2_exp
+        ,SUM(CAST(b2_pv AS BIGINT))                                                     AS b2_pv
+        ,SUM(CAST(b2_uv AS BIGINT))                                                     AS b2_uv
+        ,SUM(CAST(b3_exp AS BIGINT))                                                    AS b3_exp
+        ,SUM(CAST(b3_pv AS BIGINT))                                                     AS b3_pv
+        ,SUM(CAST(b3_uv AS BIGINT))                                                     AS b3_uv
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS bn_rov
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS bn_ror
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS b1_rov
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS b1_ror
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b2_rov
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b2_ror
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b3_rov
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b3_ror
+
+        -- ==================== C链 (全量depth, 按hop) ====================
+        ,SUM(CAST(cn_1_exp AS BIGINT))                                                  AS cn_1_exp
+        ,SUM(CAST(cn_1_pv AS BIGINT))                                                   AS cn_1_pv
+        ,SUM(CAST(cn_1_uv AS BIGINT))                                                   AS cn_1_uv
+        ,SUM(CAST(cn_2_exp AS BIGINT))                                                  AS cn_2_exp
+        ,SUM(CAST(cn_2_pv AS BIGINT))                                                   AS cn_2_pv
+        ,SUM(CAST(cn_2_uv AS BIGINT))                                                   AS cn_2_uv
+        ,SUM(CAST(cn_3_exp AS BIGINT))                                                  AS cn_3_exp
+        ,SUM(CAST(cn_3_pv AS BIGINT))                                                   AS cn_3_pv
+        ,SUM(CAST(cn_3_uv AS BIGINT))                                                   AS cn_3_uv
+        ,SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))  AS cn_total_uv
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS cn_1_rov
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS cn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_2_rov
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_3_rov
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_3_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_rov
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_ror
+
+        -- ==================== C链 (按depth拆分) ====================
+        ,SUM(CAST(c1_1_exp AS BIGINT))                                                    AS c1_1_exp
+        ,SUM(CAST(c1_1_pv AS BIGINT))                                                     AS c1_1_pv
+        ,SUM(CAST(c1_1_uv AS BIGINT))                                                     AS c1_1_uv
+        ,SUM(CAST(c1_2_exp AS BIGINT))                                                    AS c1_2_exp
+        ,SUM(CAST(c1_2_pv AS BIGINT))                                                     AS c1_2_pv
+        ,SUM(CAST(c1_2_uv AS BIGINT))                                                     AS c1_2_uv
+        ,SUM(CAST(c1_3_exp AS BIGINT))                                                    AS c1_3_exp
+        ,SUM(CAST(c1_3_pv AS BIGINT))                                                     AS c1_3_pv
+        ,SUM(CAST(c1_3_uv AS BIGINT))                                                     AS c1_3_uv
+        ,SUM(CAST(c2_1_exp AS BIGINT))                                                    AS c2_1_exp
+        ,SUM(CAST(c2_1_pv AS BIGINT))                                                     AS c2_1_pv
+        ,SUM(CAST(c2_1_uv AS BIGINT))                                                     AS c2_1_uv
+        ,SUM(CAST(c2_2_exp AS BIGINT))                                                    AS c2_2_exp
+        ,SUM(CAST(c2_2_pv AS BIGINT))                                                     AS c2_2_pv
+        ,SUM(CAST(c2_2_uv AS BIGINT))                                                     AS c2_2_uv
+        ,SUM(CAST(c2_3_exp AS BIGINT))                                                    AS c2_3_exp
+        ,SUM(CAST(c2_3_pv AS BIGINT))                                                     AS c2_3_pv
+        ,SUM(CAST(c2_3_uv AS BIGINT))                                                     AS c2_3_uv
+        ,SUM(CAST(c3_1_exp AS BIGINT))                                                    AS c3_1_exp
+        ,SUM(CAST(c3_1_pv AS BIGINT))                                                     AS c3_1_pv
+        ,SUM(CAST(c3_1_uv AS BIGINT))                                                     AS c3_1_uv
+        ,SUM(CAST(c3_2_exp AS BIGINT))                                                    AS c3_2_exp
+        ,SUM(CAST(c3_2_pv AS BIGINT))                                                     AS c3_2_pv
+        ,SUM(CAST(c3_2_uv AS BIGINT))                                                     AS c3_2_uv
+        ,SUM(CAST(c3_3_exp AS BIGINT))                                                    AS c3_3_exp
+        ,SUM(CAST(c3_3_pv AS BIGINT))                                                     AS c3_3_pv
+        ,SUM(CAST(c3_3_uv AS BIGINT))                                                     AS c3_3_uv
+        -- C链depth拆分 hop1 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS c1_1_rov
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS c1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_1_rov
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_1_rov
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_1_ror
+        -- C链depth拆分 hop2 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_2_rov
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_2_rov
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_2_rov
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_2_ror
+        -- C链depth拆分 hop3 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_3_rov
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_3_rov
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_3_rov
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_3_ror
+
+        -- ==================== D链 (全量depth, 按hop) ====================
+        ,SUM(CAST(d0 AS BIGINT))                                                        AS d0
+        ,SUM(CAST(dn_1_exp AS BIGINT))                                                  AS dn_1_exp
+        ,SUM(CAST(dn_1_pv AS BIGINT))                                                   AS dn_1_pv
+        ,SUM(CAST(dn_1_uv AS BIGINT))                                                   AS dn_1_uv
+        ,SUM(CAST(dn_2_exp AS BIGINT))                                                  AS dn_2_exp
+        ,SUM(CAST(dn_2_pv AS BIGINT))                                                   AS dn_2_pv
+        ,SUM(CAST(dn_2_uv AS BIGINT))                                                   AS dn_2_uv
+        ,SUM(CAST(dn_3_exp AS BIGINT))                                                  AS dn_3_exp
+        ,SUM(CAST(dn_3_pv AS BIGINT))                                                   AS dn_3_pv
+        ,SUM(CAST(dn_3_uv AS BIGINT))                                                   AS dn_3_uv
+        ,SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))  AS dn_total_uv
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS dn_1_rov
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS dn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_2_rov
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_3_rov
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_3_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_rov
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_ror
+
+        -- ==================== D链 (按depth拆分) ====================
+        ,SUM(CAST(d1_1_exp AS BIGINT))                                                    AS d1_1_exp
+        ,SUM(CAST(d1_1_pv AS BIGINT))                                                     AS d1_1_pv
+        ,SUM(CAST(d1_1_uv AS BIGINT))                                                     AS d1_1_uv
+        ,SUM(CAST(d1_2_exp AS BIGINT))                                                    AS d1_2_exp
+        ,SUM(CAST(d1_2_pv AS BIGINT))                                                     AS d1_2_pv
+        ,SUM(CAST(d1_2_uv AS BIGINT))                                                     AS d1_2_uv
+        ,SUM(CAST(d1_3_exp AS BIGINT))                                                    AS d1_3_exp
+        ,SUM(CAST(d1_3_pv AS BIGINT))                                                     AS d1_3_pv
+        ,SUM(CAST(d1_3_uv AS BIGINT))                                                     AS d1_3_uv
+        ,SUM(CAST(d2_1_exp AS BIGINT))                                                    AS d2_1_exp
+        ,SUM(CAST(d2_1_pv AS BIGINT))                                                     AS d2_1_pv
+        ,SUM(CAST(d2_1_uv AS BIGINT))                                                     AS d2_1_uv
+        ,SUM(CAST(d2_2_exp AS BIGINT))                                                    AS d2_2_exp
+        ,SUM(CAST(d2_2_pv AS BIGINT))                                                     AS d2_2_pv
+        ,SUM(CAST(d2_2_uv AS BIGINT))                                                     AS d2_2_uv
+        ,SUM(CAST(d2_3_exp AS BIGINT))                                                    AS d2_3_exp
+        ,SUM(CAST(d2_3_pv AS BIGINT))                                                     AS d2_3_pv
+        ,SUM(CAST(d2_3_uv AS BIGINT))                                                     AS d2_3_uv
+        ,SUM(CAST(d3_1_exp AS BIGINT))                                                    AS d3_1_exp
+        ,SUM(CAST(d3_1_pv AS BIGINT))                                                     AS d3_1_pv
+        ,SUM(CAST(d3_1_uv AS BIGINT))                                                     AS d3_1_uv
+        ,SUM(CAST(d3_2_exp AS BIGINT))                                                    AS d3_2_exp
+        ,SUM(CAST(d3_2_pv AS BIGINT))                                                     AS d3_2_pv
+        ,SUM(CAST(d3_2_uv AS BIGINT))                                                     AS d3_2_uv
+        ,SUM(CAST(d3_3_exp AS BIGINT))                                                    AS d3_3_exp
+        ,SUM(CAST(d3_3_pv AS BIGINT))                                                     AS d3_3_pv
+        ,SUM(CAST(d3_3_uv AS BIGINT))                                                     AS d3_3_uv
+        -- D链depth拆分 hop1 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS d1_1_rov
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS d1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_1_rov
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_1_rov
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_1_ror
+        -- D链depth拆分 hop2 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_2_rov
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_2_rov
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_2_rov
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_2_ror
+        -- D链depth拆分 hop3 rov/ror
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_3_rov
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_3_rov
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_3_rov
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_3_ror
+
+        -- ==================== 全链路 ====================
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))
+            + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+            + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+                                                                                        AS all_return_n_uv
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(COUNT(1), 0)
+        , 0), 6)                                                                        AS all_rovn
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_rov
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_ror
+
+
+-- =====================================================================
+-- FROM + GROUP BY CUBE
+-- =====================================================================
+
+FROM    t_wide
+
+GROUP BY CUBE(
+            user_type
+            ,hh_bucket
+            ,head_merge_leve2
+            ,vid_merge_leve2
+            ,vid_id
+        )
+
+ORDER BY exposure_cnt DESC
+;

+ 632 - 0
table_gen/test_4.sql

@@ -0,0 +1,632 @@
+-- =====================================================================
+-- 曝光回流链路 CUBE 聚合表 (基于 wide 宽表, 增加用户/品类维度 + 模型预估指标)
+-- 维度: user_type × hh_bucket × head_merge_leve2 × vid_merge_leve2 × vid_id (CUBE)
+-- 参考: de.sql + dwd_recsys_alg_exposure_agg_20260209
+-- =====================================================================
+
+-- -- DROP TABLE IF EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209;
+-- CREATE TABLE IF NOT EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209 (
+--     -- ==================== 维度列 ====================
+--     dt                         STRING    COMMENT '日期'
+--     ,user_type                  STRING    COMMENT '用户拉活量分层(R0&新用户/R1-50/R_180_330等,汇总为SUM)'
+--     ,hh_bucket                STRING    COMMENT '小时段(00-03/04-07/.../20-23,汇总为SUM)'
+--     ,head_merge_leve2         STRING    COMMENT '进入内容品类(headvideoid品类,汇总为SUM)'
+--     ,vid_merge_leve2          STRING    COMMENT '推荐内容品类(vid品类,TOP10曝光+其他,汇总为SUM)'
+--     ,vid_id                   STRING    COMMENT '内容id(品类曝光TOP1+其他,汇总为SUM)'
+
+--     -- ==================== 基础流量 ====================
+--     ,exposure_cnt             BIGINT    COMMENT '曝光次数'
+--     ,exposure_uv              BIGINT    COMMENT '曝光人数(mid去重)'
+--     ,vid_cnt                  BIGINT    COMMENT '视频个数(vid去重)'
+--     ,exposure_per_user        DOUBLE    COMMENT '人均曝光次数 = 曝光次数/曝光人数'
+
+--     -- ==================== 分享 & 回流漏斗 ====================
+--     ,share_exposure_cnt       BIGINT    COMMENT '产生分享的曝光数'
+--     ,share_cnt                BIGINT    COMMENT '分享总次数'
+--     ,return_exposure_cnt      BIGINT    COMMENT '产生回流的曝光数(含自身) = SUM(is_return_n)'
+--     ,return_exposure_cnt_noself BIGINT  COMMENT '产生回流的曝光数(非自身) = SUM(is_return_noself)'
+--     ,return_uv                BIGINT    COMMENT '回流人数(含自身) = SUM(return_n_uv)'
+--     ,return_uv_noself         BIGINT    COMMENT '回流人数(非自身) = SUM(return_n_uv_noself)'
+--     ,share_rate               DOUBLE    COMMENT '分享率 = share_exposure_cnt/exposure_cnt'
+--     ,return_rate              DOUBLE    COMMENT '回流率(含自身) = return_exposure_cnt/exposure_cnt'
+--     ,return_rate_noself       DOUBLE    COMMENT '回流率(非自身) = return_exposure_cnt_noself/exposure_cnt'
+--     ,share_return_rate        DOUBLE    COMMENT '分享→回流转化率(非自身) = return_exposure_cnt_noself/share_exposure_cnt'
+
+--     -- ==================== 模型预估: STR (曝光→非自身回流概率) ====================
+--     ,str_real                 DOUBLE    COMMENT '= return_rate_noself, 模型label'
+--     ,str_pred                 DOUBLE    COMMENT 'STR预估 = SUM(str_pred)/exposure_cnt'
+--     ,str_copc                 DOUBLE    COMMENT 'STR copc = str_real/str_pred'
+--     ,str_mae                  DOUBLE    COMMENT 'STR MAE = AVG(|str_pred - str_real|)'
+--     ,str_var                  DOUBLE    COMMENT 'STR VAR = VARIANCE(str_pred - str_real)'
+
+--     -- ==================== 模型预估: ROSN (条件回流UV, 非自身) ====================
+--     ,rosn_real                DOUBLE    COMMENT '= return_uv_noself/return_exposure_cnt_noself, 模型label'
+--     ,rosn_pred                DOUBLE    COMMENT 'ROSN预估 = SUM(rosn_pred WHERE is_return_noself=1)/SUM(is_return_noself)'
+--     ,rosn_copc                DOUBLE    COMMENT 'ROSN copc = rosn_real/rosn_pred'
+--     ,rosn_pred_origin         DOUBLE    COMMENT 'ROSN原始预估均值 = AVG(rosn_pred_origin)'
+--     ,rosn_mae                 DOUBLE    COMMENT 'ROSN MAE = AVG(|rosn_pred - rosn_real|) WHERE is_return_noself=1'
+--     ,rosn_var                 DOUBLE    COMMENT 'ROSN VAR = VARIANCE(rosn_pred - rosn_real) WHERE is_return_noself=1'
+
+--     -- ==================== 模型预估: ROVN (STR×ROSN) ====================
+--     ,rovn_real                DOUBLE    COMMENT '= return_uv_noself/exposure_cnt, 模型label'
+--     ,rovn_pred                DOUBLE    COMMENT 'rovn预估 = AVG(str_pred*rosn_pred)'
+--     ,rovn_copc                DOUBLE    COMMENT 'rovn copc = rovn_real/rovn_pred'
+--     ,rovn_mae                 DOUBLE    COMMENT 'rovn MAE = AVG(|rovn_pred - rovn_real|)'
+--     ,rovn_var                 DOUBLE    COMMENT 'rovn VAR = VARIANCE(rovn_pred - rovn_real)'
+--     ,sortscore_avg            DOUBLE    COMMENT 'sortscore均值'
+
+--     -- ==================== B链 (分享→点击) ====================
+--     ,bn_uv                    BIGINT    COMMENT 'B链全量: 回流去重人数'
+--     ,bn_pv                    BIGINT    COMMENT 'B链全量: 回流点击次数'
+--     ,bn_exp                   BIGINT    COMMENT 'B链全量: 回流session曝光数'
+--     ,bn_ror                   DOUBLE    COMMENT 'bn_uv/exposure_uv'
+--     ,bn_rov                   DOUBLE    COMMENT 'bn_uv/exposure_cnt'
+--     ,b1_uv                    BIGINT    COMMENT 'B链depth=1: 回流去重人数'
+--     ,b1_pv                    BIGINT    COMMENT 'B链depth=1: 回流点击次数'
+--     ,b1_exp                   BIGINT    COMMENT 'B链depth=1: 回流session曝光数'
+--     ,b1_ror                   DOUBLE    COMMENT 'b1_uv/exposure_uv'
+--     ,b1_rov                   DOUBLE    COMMENT 'b1_uv/exposure_cnt'
+--     ,b2_uv                    BIGINT    COMMENT 'B链depth=2: 回流去重人数'
+--     ,b2_pv                    BIGINT    COMMENT 'B链depth=2: 回流点击次数'
+--     ,b2_exp                   BIGINT    COMMENT 'B链depth=2: 回流session曝光数'
+--     ,b2_ror                   DOUBLE    COMMENT 'b2_uv/b1_uv'
+--     ,b2_rov                   DOUBLE    COMMENT 'b2_uv/b1_exp'
+--     ,b3_uv                    BIGINT    COMMENT 'B链depth=3: 回流去重人数'
+--     ,b3_pv                    BIGINT    COMMENT 'B链depth=3: 回流点击次数'
+--     ,b3_exp                   BIGINT    COMMENT 'B链depth=3: 回流session曝光数'
+--     ,b3_ror                   DOUBLE    COMMENT 'b3_uv/b2_uv'
+--     ,b3_rov                   DOUBLE    COMMENT 'b3_uv/b2_exp'
+
+--     -- ==================== C链 (全量depth, 按hop) ====================
+--     ,cn_1_uv                  BIGINT    COMMENT 'C链hop1: 回流去重人数'
+--     ,cn_1_pv                  BIGINT    COMMENT 'C链hop1: 回流点击次数'
+--     ,cn_1_exp                 BIGINT    COMMENT 'C链hop1: 回流session曝光数'
+--     ,cn_1_ror                 DOUBLE    COMMENT 'cn_1_uv/bn_uv'
+--     ,cn_1_rov                 DOUBLE    COMMENT 'cn_1_uv/bn_exp'
+--     ,cn_2_uv                  BIGINT    COMMENT 'C链hop2: 回流去重人数'
+--     ,cn_2_pv                  BIGINT    COMMENT 'C链hop2: 回流点击次数'
+--     ,cn_2_exp                 BIGINT    COMMENT 'C链hop2: 回流session曝光数'
+--     ,cn_2_ror                 DOUBLE    COMMENT 'cn_2_uv/cn_1_uv'
+--     ,cn_2_rov                 DOUBLE    COMMENT 'cn_2_uv/cn_1_exp'
+--     ,cn_3_uv                  BIGINT    COMMENT 'C链hop3: 回流去重人数'
+--     ,cn_3_pv                  BIGINT    COMMENT 'C链hop3: 回流点击次数'
+--     ,cn_3_exp                 BIGINT    COMMENT 'C链hop3: 回流session曝光数'
+--     ,cn_3_ror                 DOUBLE    COMMENT 'cn_3_uv/cn_2_uv'
+--     ,cn_3_rov                 DOUBLE    COMMENT 'cn_3_uv/cn_2_exp'
+--     ,cn_total_uv              BIGINT    COMMENT 'C链合计UV'
+--     ,cn_total_ror             DOUBLE    COMMENT 'cn_total_uv/bn_uv'
+--     ,cn_total_rov             DOUBLE    COMMENT 'cn_total_uv/bn_exp'
+--     -- C链 depth拆分 hop1
+--     ,c1_1_uv                  BIGINT    COMMENT 'C链d1-hop1: 回流去重人数'
+--     ,c1_1_pv                  BIGINT    COMMENT 'C链d1-hop1: 回流点击次数'
+--     ,c1_1_exp                 BIGINT    COMMENT 'C链d1-hop1: 回流session曝光数'
+--     ,c1_1_ror                 DOUBLE    COMMENT 'c1_1_uv/bn_uv'
+--     ,c1_1_rov                 DOUBLE    COMMENT 'c1_1_uv/bn_exp'
+--     ,c2_1_uv                  BIGINT    COMMENT 'C链d2-hop1: 回流去重人数'
+--     ,c2_1_pv                  BIGINT    COMMENT 'C链d2-hop1: 回流点击次数'
+--     ,c2_1_exp                 BIGINT    COMMENT 'C链d2-hop1: 回流session曝光数'
+--     ,c2_1_ror                 DOUBLE    COMMENT 'c2_1_uv/c1_1_uv'
+--     ,c2_1_rov                 DOUBLE    COMMENT 'c2_1_uv/c1_1_exp'
+--     ,c3_1_uv                  BIGINT    COMMENT 'C链d3-hop1: 回流去重人数'
+--     ,c3_1_pv                  BIGINT    COMMENT 'C链d3-hop1: 回流点击次数'
+--     ,c3_1_exp                 BIGINT    COMMENT 'C链d3-hop1: 回流session曝光数'
+--     ,c3_1_ror                 DOUBLE    COMMENT 'c3_1_uv/c2_1_uv'
+--     ,c3_1_rov                 DOUBLE    COMMENT 'c3_1_uv/c2_1_exp'
+--     -- C链 depth拆分 hop2
+--     ,c1_2_uv                  BIGINT    COMMENT 'C链d1-hop2: 回流去重人数'
+--     ,c1_2_pv                  BIGINT    COMMENT 'C链d1-hop2: 回流点击次数'
+--     ,c1_2_exp                 BIGINT    COMMENT 'C链d1-hop2: 回流session曝光数'
+--     ,c1_2_ror                 DOUBLE    COMMENT 'c1_2_uv/cn_1_uv'
+--     ,c1_2_rov                 DOUBLE    COMMENT 'c1_2_uv/cn_1_exp'
+--     ,c2_2_uv                  BIGINT    COMMENT 'C链d2-hop2: 回流去重人数'
+--     ,c2_2_pv                  BIGINT    COMMENT 'C链d2-hop2: 回流点击次数'
+--     ,c2_2_exp                 BIGINT    COMMENT 'C链d2-hop2: 回流session曝光数'
+--     ,c2_2_ror                 DOUBLE    COMMENT 'c2_2_uv/c1_2_uv'
+--     ,c2_2_rov                 DOUBLE    COMMENT 'c2_2_uv/c1_2_exp'
+--     ,c3_2_uv                  BIGINT    COMMENT 'C链d3-hop2: 回流去重人数'
+--     ,c3_2_pv                  BIGINT    COMMENT 'C链d3-hop2: 回流点击次数'
+--     ,c3_2_exp                 BIGINT    COMMENT 'C链d3-hop2: 回流session曝光数'
+--     ,c3_2_ror                 DOUBLE    COMMENT 'c3_2_uv/c2_2_uv'
+--     ,c3_2_rov                 DOUBLE    COMMENT 'c3_2_uv/c2_2_exp'
+--     -- C链 depth拆分 hop3
+--     ,c1_3_uv                  BIGINT    COMMENT 'C链d1-hop3: 回流去重人数'
+--     ,c1_3_pv                  BIGINT    COMMENT 'C链d1-hop3: 回流点击次数'
+--     ,c1_3_exp                 BIGINT    COMMENT 'C链d1-hop3: 回流session曝光数'
+--     ,c1_3_ror                 DOUBLE    COMMENT 'c1_3_uv/cn_2_uv'
+--     ,c1_3_rov                 DOUBLE    COMMENT 'c1_3_uv/cn_2_exp'
+--     ,c2_3_uv                  BIGINT    COMMENT 'C链d2-hop3: 回流去重人数'
+--     ,c2_3_pv                  BIGINT    COMMENT 'C链d2-hop3: 回流点击次数'
+--     ,c2_3_exp                 BIGINT    COMMENT 'C链d2-hop3: 回流session曝光数'
+--     ,c2_3_ror                 DOUBLE    COMMENT 'c2_3_uv/c1_3_uv'
+--     ,c2_3_rov                 DOUBLE    COMMENT 'c2_3_uv/c1_3_exp'
+--     ,c3_3_uv                  BIGINT    COMMENT 'C链d3-hop3: 回流去重人数'
+--     ,c3_3_pv                  BIGINT    COMMENT 'C链d3-hop3: 回流点击次数'
+--     ,c3_3_exp                 BIGINT    COMMENT 'C链d3-hop3: 回流session曝光数'
+--     ,c3_3_ror                 DOUBLE    COMMENT 'c3_3_uv/c2_3_uv'
+--     ,c3_3_rov                 DOUBLE    COMMENT 'c3_3_uv/c2_3_exp'
+
+--     -- ==================== D链 (session内后续曝光传播) ====================
+--     ,d0                       BIGINT    COMMENT 'D链初始成本: session内后续曝光数'
+--     ,dn_1_uv                  BIGINT    COMMENT 'D链hop1: 回流去重人数'
+--     ,dn_1_pv                  BIGINT    COMMENT 'D链hop1: 回流点击次数'
+--     ,dn_1_exp                 BIGINT    COMMENT 'D链hop1: 回流session曝光数'
+--     ,dn_1_ror                 DOUBLE    COMMENT 'dn_1_uv/exposure_uv'
+--     ,dn_1_rov                 DOUBLE    COMMENT 'dn_1_uv/d0'
+--     ,dn_2_uv                  BIGINT    COMMENT 'D链hop2: 回流去重人数'
+--     ,dn_2_pv                  BIGINT    COMMENT 'D链hop2: 回流点击次数'
+--     ,dn_2_exp                 BIGINT    COMMENT 'D链hop2: 回流session曝光数'
+--     ,dn_2_ror                 DOUBLE    COMMENT 'dn_2_uv/dn_1_uv'
+--     ,dn_2_rov                 DOUBLE    COMMENT 'dn_2_uv/dn_1_exp'
+--     ,dn_3_uv                  BIGINT    COMMENT 'D链hop3: 回流去重人数'
+--     ,dn_3_pv                  BIGINT    COMMENT 'D链hop3: 回流点击次数'
+--     ,dn_3_exp                 BIGINT    COMMENT 'D链hop3: 回流session曝光数'
+--     ,dn_3_ror                 DOUBLE    COMMENT 'dn_3_uv/dn_2_uv'
+--     ,dn_3_rov                 DOUBLE    COMMENT 'dn_3_uv/dn_2_exp'
+--     ,dn_total_uv              BIGINT    COMMENT 'D链合计UV'
+--     ,dn_total_ror             DOUBLE    COMMENT 'dn_total_uv/exposure_uv'
+--     ,dn_total_rov             DOUBLE    COMMENT 'dn_total_uv/d0'
+--     -- D链 depth拆分 hop1
+--     ,d1_1_uv                  BIGINT    COMMENT 'D链d1-hop1: 回流去重人数'
+--     ,d1_1_pv                  BIGINT    COMMENT 'D链d1-hop1: 回流点击次数'
+--     ,d1_1_exp                 BIGINT    COMMENT 'D链d1-hop1: 回流session曝光数'
+--     ,d1_1_ror                 DOUBLE    COMMENT 'd1_1_uv/exposure_uv'
+--     ,d1_1_rov                 DOUBLE    COMMENT 'd1_1_uv/d0'
+--     ,d2_1_uv                  BIGINT    COMMENT 'D链d2-hop1: 回流去重人数'
+--     ,d2_1_pv                  BIGINT    COMMENT 'D链d2-hop1: 回流点击次数'
+--     ,d2_1_exp                 BIGINT    COMMENT 'D链d2-hop1: 回流session曝光数'
+--     ,d2_1_ror                 DOUBLE    COMMENT 'd2_1_uv/d1_1_uv'
+--     ,d2_1_rov                 DOUBLE    COMMENT 'd2_1_uv/d1_1_exp'
+--     ,d3_1_uv                  BIGINT    COMMENT 'D链d3-hop1: 回流去重人数'
+--     ,d3_1_pv                  BIGINT    COMMENT 'D链d3-hop1: 回流点击次数'
+--     ,d3_1_exp                 BIGINT    COMMENT 'D链d3-hop1: 回流session曝光数'
+--     ,d3_1_ror                 DOUBLE    COMMENT 'd3_1_uv/d2_1_uv'
+--     ,d3_1_rov                 DOUBLE    COMMENT 'd3_1_uv/d2_1_exp'
+--     -- D链 depth拆分 hop2
+--     ,d1_2_uv                  BIGINT    COMMENT 'D链d1-hop2: 回流去重人数'
+--     ,d1_2_pv                  BIGINT    COMMENT 'D链d1-hop2: 回流点击次数'
+--     ,d1_2_exp                 BIGINT    COMMENT 'D链d1-hop2: 回流session曝光数'
+--     ,d1_2_ror                 DOUBLE    COMMENT 'd1_2_uv/dn_1_uv'
+--     ,d1_2_rov                 DOUBLE    COMMENT 'd1_2_uv/dn_1_exp'
+--     ,d2_2_uv                  BIGINT    COMMENT 'D链d2-hop2: 回流去重人数'
+--     ,d2_2_pv                  BIGINT    COMMENT 'D链d2-hop2: 回流点击次数'
+--     ,d2_2_exp                 BIGINT    COMMENT 'D链d2-hop2: 回流session曝光数'
+--     ,d2_2_ror                 DOUBLE    COMMENT 'd2_2_uv/d1_2_uv'
+--     ,d2_2_rov                 DOUBLE    COMMENT 'd2_2_uv/d1_2_exp'
+--     ,d3_2_uv                  BIGINT    COMMENT 'D链d3-hop2: 回流去重人数'
+--     ,d3_2_pv                  BIGINT    COMMENT 'D链d3-hop2: 回流点击次数'
+--     ,d3_2_exp                 BIGINT    COMMENT 'D链d3-hop2: 回流session曝光数'
+--     ,d3_2_ror                 DOUBLE    COMMENT 'd3_2_uv/d2_2_uv'
+--     ,d3_2_rov                 DOUBLE    COMMENT 'd3_2_uv/d2_2_exp'
+--     -- D链 depth拆分 hop3
+--     ,d1_3_uv                  BIGINT    COMMENT 'D链d1-hop3: 回流去重人数'
+--     ,d1_3_pv                  BIGINT    COMMENT 'D链d1-hop3: 回流点击次数'
+--     ,d1_3_exp                 BIGINT    COMMENT 'D链d1-hop3: 回流session曝光数'
+--     ,d1_3_ror                 DOUBLE    COMMENT 'd1_3_uv/dn_2_uv'
+--     ,d1_3_rov                 DOUBLE    COMMENT 'd1_3_uv/dn_2_exp'
+--     ,d2_3_uv                  BIGINT    COMMENT 'D链d2-hop3: 回流去重人数'
+--     ,d2_3_pv                  BIGINT    COMMENT 'D链d2-hop3: 回流点击次数'
+--     ,d2_3_exp                 BIGINT    COMMENT 'D链d2-hop3: 回流session曝光数'
+--     ,d2_3_ror                 DOUBLE    COMMENT 'd2_3_uv/d1_3_uv'
+--     ,d2_3_rov                 DOUBLE    COMMENT 'd2_3_uv/d1_3_exp'
+--     ,d3_3_uv                  BIGINT    COMMENT 'D链d3-hop3: 回流去重人数'
+--     ,d3_3_pv                  BIGINT    COMMENT 'D链d3-hop3: 回流点击次数'
+--     ,d3_3_exp                 BIGINT    COMMENT 'D链d3-hop3: 回流session曝光数'
+--     ,d3_3_ror                 DOUBLE    COMMENT 'd3_3_uv/d2_3_uv'
+--     ,d3_3_rov                 DOUBLE    COMMENT 'd3_3_uv/d2_3_exp'
+
+--     -- ==================== 全链路 ====================
+--     ,all_return_n_uv          BIGINT    COMMENT '全链路拉回UV = B + C + D'
+--     ,all_rovn                 DOUBLE    COMMENT 'all_return_n_uv/exposure_cnt'
+--     ,all_ror                  DOUBLE    COMMENT 'all_return_n_uv/exposure_uv'
+--     ,all_rov                  DOUBLE    COMMENT 'all_return_n_uv/exposure_cnt'
+-- )
+-- COMMENT '曝光回流链路CUBE聚合-宽表版 (5维度: 用户分层/小时段/进入品类TOP1/推荐品类TOP10/内容idTOP1)'
+-- ;
+
+
+-- -- =====================================================================
+-- -- INSERT: 从 wide 宽表聚合, CUBE 全维度组合
+-- -- =====================================================================
+
+-- -- SELECT * FROM loghubods.dwd_recsys_alg_exposure_agg_wide_20260209 WHERE dt = '${dt}' ORDER BY exposure_cnt DESC LIMIT 100;
+
+-- INSERT OVERWRITE TABLE loghubods.dwd_recsys_alg_exposure_agg_wide_20260209
+
+WITH
+-- 用户拉活量分层
+t_user_type AS (
+    SELECT  DISTINCT type, openid
+    FROM    loghubods.mid_share_return_people_1year
+    WHERE   dt = TO_CHAR(DATEADD(TO_DATE('${dt}','YYYYMMDD'),-1,'dd'),'YYYYMMDD')
+    AND     type IS NOT NULL
+    AND     type != 'S_ALL'
+    AND     type NOT REGEXP 'R50'
+)
+-- 模型预估分数
+,t_score AS (
+    SELECT  apptype
+            ,videoid
+            ,recommendtraceid
+            ,scoresmap
+            ,sortscore
+    FROM    (
+                SELECT  apptype
+                        ,videoid
+                        ,recommendtraceid
+                        ,scoresmap
+                        ,sortscore
+                        ,ROW_NUMBER() OVER (PARTITION BY apptype,videoid,recommendtraceid) AS rn
+                FROM    loghubods.statistics_log_hour
+                WHERE   dt LIKE '${dt}%'
+                AND     scoresmap IS NOT NULL
+            )
+    WHERE   rn = 1
+)
+-- TOP1 进入内容品类(场): 按回流人数取 TOP1
+,t_top_head_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.headvideoid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY SUM(CAST(is_return_noself AS BIGINT)) DESC
+    LIMIT   1
+)
+-- TOP10 推荐内容品类(货): 按曝光次数取 TOP10
+,t_top_vid_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY COUNT(1) DESC
+    LIMIT   10
+)
+-- TOP1 内容id(货): 每品类按曝光次数取 TOP1 (曝光>10w)
+,t_top_vid AS (
+    SELECT  merge_leve2, vid
+    FROM    (
+                SELECT  vt.merge_leve2
+                        ,base.vid
+                        ,COUNT(1)                                                               AS exp_cnt
+                        ,ROW_NUMBER() OVER (PARTITION BY vt.merge_leve2 ORDER BY COUNT(1) DESC) AS rk
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+                JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+                WHERE   base.dt = '${dt}'
+                AND     vt.merge_leve2 IS NOT NULL
+                GROUP BY vt.merge_leve2, base.vid
+                HAVING  exp_cnt > 100000
+            )
+    WHERE   rk <= 1
+)
+-- 宽表
+,t_wide AS (
+    SELECT  base.*
+            ,CASE WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                  WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                  WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                  ELSE e.type
+             END AS user_type
+            ,CASE WHEN th.merge_leve2 IS NOT NULL THEN vt_head.merge_leve2 ELSE '其他' END AS head_merge_leve2
+            ,CASE WHEN tv.merge_leve2 IS NOT NULL THEN vt_vid.merge_leve2  ELSE '其他' END AS vid_merge_leve2
+            ,CASE WHEN ti.vid IS NOT NULL          THEN base.vid           ELSE '其他' END AS vid_id
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.fmRov') AS DOUBLE) AS str_pred
+            ,1.22*POW(CAST(GET_JSON_OBJECT(e1.scoresmap,'$.NorXGBScore') AS DOUBLE),1.15) AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.hasReturnRovScore') AS DOUBLE) AS rosn_pred_origin
+            ,e1.sortscore
+            ,CASE
+                WHEN CAST(hh AS INT) BETWEEN 0  AND 3  THEN '00-03'
+                WHEN CAST(hh AS INT) BETWEEN 4  AND 7  THEN '04-07'
+                WHEN CAST(hh AS INT) BETWEEN 8  AND 11 THEN '08-11'
+                WHEN CAST(hh AS INT) BETWEEN 12 AND 15 THEN '12-15'
+                WHEN CAST(hh AS INT) BETWEEN 16 AND 19 THEN '16-19'
+                WHEN CAST(hh AS INT) BETWEEN 20 AND 23 THEN '20-23'
+                ELSE '-'
+             END AS hh_bucket
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    LEFT JOIN t_user_type e
+    ON      SUBSTRING_INDEX(base.mid,'weixin_openid_',-1) = e.openid
+    LEFT JOIN loghubods.video_merge_tag vt_head
+    ON      base.headvideoid = vt_head.videoid
+    LEFT JOIN loghubods.video_merge_tag vt_vid
+    ON      base.vid = vt_vid.videoid
+    LEFT JOIN t_score e1
+    ON      base.apptype = e1.apptype
+    AND     base.vid = e1.videoid
+    AND     base.recomtraceid = e1.recommendtraceid
+    LEFT JOIN t_top_head_cate th
+    ON      vt_head.merge_leve2 = th.merge_leve2
+    LEFT JOIN t_top_vid_cate tv
+    ON      vt_vid.merge_leve2 = tv.merge_leve2
+    LEFT JOIN t_top_vid ti
+    ON      base.vid = ti.vid
+    WHERE   base.dt = '${dt}'
+)
+
+SELECT
+        -- ==================== 维度列 ====================
+        '${dt}'                                                                                     AS dt
+        ,CASE WHEN GROUPING(user_type) = 1 THEN 'SUM' ELSE NVL(user_type, 'SUM') END              AS user_type
+        ,CASE WHEN GROUPING(hh_bucket) = 1 THEN 'SUM' ELSE NVL(hh_bucket, 'SUM') END              AS hh_bucket
+        ,CASE WHEN GROUPING(head_merge_leve2) = 1 THEN 'SUM' ELSE NVL(head_merge_leve2, 'SUM') END AS head_merge_leve2
+        ,CASE WHEN GROUPING(vid_merge_leve2) = 1 THEN 'SUM' ELSE NVL(vid_merge_leve2, 'SUM') END   AS vid_merge_leve2
+        ,CASE WHEN GROUPING(vid_id) = 1 THEN 'SUM' ELSE NVL(vid_id, 'SUM') END                     AS vid_id
+
+        -- ==================== 基础流量 ====================
+        ,COUNT(1)                                                                       AS exposure_cnt
+        ,COUNT(DISTINCT mid)                                                            AS exposure_uv
+        ,COUNT(DISTINCT vid)                                                            AS vid_cnt
+        ,ROUND(COUNT(1) / COUNT(DISTINCT mid), 4)                                      AS exposure_per_user
+
+        -- ==================== 分享 & 回流漏斗 ====================
+        ,SUM(CAST(is_share AS BIGINT))                                                  AS share_exposure_cnt
+        ,SUM(CAST(share_cnt AS BIGINT))                                                 AS share_cnt
+        ,SUM(CAST(is_return_n AS BIGINT))                                               AS return_exposure_cnt
+        ,SUM(CAST(is_return_noself AS BIGINT))                                          AS return_exposure_cnt_noself
+        ,SUM(CAST(return_n_uv AS BIGINT))                                               AS return_uv
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))                                        AS return_uv_noself
+        ,ROUND(COALESCE(SUM(CAST(is_share AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                            AS share_rate
+        ,ROUND(COALESCE(SUM(CAST(is_return_n AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                         AS return_rate
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                    AS return_rate_noself
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(CAST(SUM(CAST(is_share AS BIGINT)) AS DOUBLE), 0), 0), 6)               AS share_return_rate
+
+        -- ==================== 模型预估: STR (曝光→非自身回流概率) ====================
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS str_real
+        ,ROUND(COALESCE(SUM(str_pred) / NULLIF(COUNT(1), 0), 0), 6)                          AS str_pred
+        ,ROUND(
+            (SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(SUM(str_pred) / NULLIF(COUNT(1), 0), 0)
+        , 4)                                                                                   AS str_copc
+        ,ROUND(AVG(ABS(str_pred - CAST(is_return_noself AS BIGINT))), 6)                      AS str_mae
+        ,ROUND(VARIANCE(str_pred - CAST(is_return_noself AS BIGINT)), 6)                      AS str_var
+
+        -- ==================== 模型预估: ROSN (条件回流UV, 非自身) ====================
+        ,ROUND(COALESCE(
+            SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0)
+        , 0), 6)                                                                               AS rosn_real
+        ,ROUND(COALESCE(SUM(CASE WHEN CAST(is_return_noself AS BIGINT) = 1 THEN rosn_pred END) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0), 6)  AS rosn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0))
+            / NULLIF(SUM(CASE WHEN CAST(is_return_noself AS BIGINT) = 1 THEN rosn_pred END) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0)
+        , 4)                                                                                   AS rosn_copc
+        ,ROUND(AVG(rosn_pred_origin), 6)                                                      AS rosn_pred_origin
+        ,ROUND(AVG(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN ABS(rosn_pred - CAST(return_n_uv_noself AS BIGINT))
+            END
+        ), 6)                                                                                  AS rosn_mae
+        ,ROUND(VARIANCE(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN rosn_pred - CAST(return_n_uv_noself AS BIGINT)
+            END
+        ), 6)                                                                                  AS rosn_var
+
+        -- ==================== 模型预估: ROVN (STR×ROSN) ====================
+        ,ROUND(COALESCE(SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS rovn_real
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                                    AS rovn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                                     AS rovn_copc
+        ,ROUND(AVG(ABS(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT))), 6)            AS rovn_mae
+        ,ROUND(VARIANCE(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT)), 6)        AS rovn_var
+        ,ROUND(AVG(CAST(sortscore AS DOUBLE)), 6)                                               AS sortscore_avg
+
+        -- ==================== B链 ====================
+        ,SUM(CAST(bn_uv AS BIGINT))                                                     AS bn_uv
+        ,SUM(CAST(bn_pv AS BIGINT))                                                     AS bn_pv
+        ,SUM(CAST(bn_exp AS BIGINT))                                                    AS bn_exp
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS bn_ror
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS bn_rov
+        ,SUM(CAST(b1_uv AS BIGINT))                                                     AS b1_uv
+        ,SUM(CAST(b1_pv AS BIGINT))                                                     AS b1_pv
+        ,SUM(CAST(b1_exp AS BIGINT))                                                    AS b1_exp
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS b1_ror
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS b1_rov
+        ,SUM(CAST(b2_uv AS BIGINT))                                                     AS b2_uv
+        ,SUM(CAST(b2_pv AS BIGINT))                                                     AS b2_pv
+        ,SUM(CAST(b2_exp AS BIGINT))                                                    AS b2_exp
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b2_ror
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b2_rov
+        ,SUM(CAST(b3_uv AS BIGINT))                                                     AS b3_uv
+        ,SUM(CAST(b3_pv AS BIGINT))                                                     AS b3_pv
+        ,SUM(CAST(b3_exp AS BIGINT))                                                    AS b3_exp
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b3_ror
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b3_rov
+
+        -- ==================== C链 (全量depth, 按hop) ====================
+        ,SUM(CAST(cn_1_uv AS BIGINT))                                                   AS cn_1_uv
+        ,SUM(CAST(cn_1_pv AS BIGINT))                                                   AS cn_1_pv
+        ,SUM(CAST(cn_1_exp AS BIGINT))                                                  AS cn_1_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS cn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS cn_1_rov
+        ,SUM(CAST(cn_2_uv AS BIGINT))                                                   AS cn_2_uv
+        ,SUM(CAST(cn_2_pv AS BIGINT))                                                   AS cn_2_pv
+        ,SUM(CAST(cn_2_exp AS BIGINT))                                                  AS cn_2_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_2_rov
+        ,SUM(CAST(cn_3_uv AS BIGINT))                                                   AS cn_3_uv
+        ,SUM(CAST(cn_3_pv AS BIGINT))                                                   AS cn_3_pv
+        ,SUM(CAST(cn_3_exp AS BIGINT))                                                  AS cn_3_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_3_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_3_rov
+        ,SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))  AS cn_total_uv
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_rov
+
+        -- ==================== C链 (按depth拆分) ====================
+        -- hop1
+        ,SUM(CAST(c1_1_uv AS BIGINT))                                                     AS c1_1_uv
+        ,SUM(CAST(c1_1_pv AS BIGINT))                                                     AS c1_1_pv
+        ,SUM(CAST(c1_1_exp AS BIGINT))                                                    AS c1_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS c1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS c1_1_rov
+        ,SUM(CAST(c2_1_uv AS BIGINT))                                                     AS c2_1_uv
+        ,SUM(CAST(c2_1_pv AS BIGINT))                                                     AS c2_1_pv
+        ,SUM(CAST(c2_1_exp AS BIGINT))                                                    AS c2_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_1_rov
+        ,SUM(CAST(c3_1_uv AS BIGINT))                                                     AS c3_1_uv
+        ,SUM(CAST(c3_1_pv AS BIGINT))                                                     AS c3_1_pv
+        ,SUM(CAST(c3_1_exp AS BIGINT))                                                    AS c3_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_1_rov
+        -- hop2
+        ,SUM(CAST(c1_2_uv AS BIGINT))                                                     AS c1_2_uv
+        ,SUM(CAST(c1_2_pv AS BIGINT))                                                     AS c1_2_pv
+        ,SUM(CAST(c1_2_exp AS BIGINT))                                                    AS c1_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_2_rov
+        ,SUM(CAST(c2_2_uv AS BIGINT))                                                     AS c2_2_uv
+        ,SUM(CAST(c2_2_pv AS BIGINT))                                                     AS c2_2_pv
+        ,SUM(CAST(c2_2_exp AS BIGINT))                                                    AS c2_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_2_rov
+        ,SUM(CAST(c3_2_uv AS BIGINT))                                                     AS c3_2_uv
+        ,SUM(CAST(c3_2_pv AS BIGINT))                                                     AS c3_2_pv
+        ,SUM(CAST(c3_2_exp AS BIGINT))                                                    AS c3_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_2_rov
+        -- hop3
+        ,SUM(CAST(c1_3_uv AS BIGINT))                                                     AS c1_3_uv
+        ,SUM(CAST(c1_3_pv AS BIGINT))                                                     AS c1_3_pv
+        ,SUM(CAST(c1_3_exp AS BIGINT))                                                    AS c1_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_3_rov
+        ,SUM(CAST(c2_3_uv AS BIGINT))                                                     AS c2_3_uv
+        ,SUM(CAST(c2_3_pv AS BIGINT))                                                     AS c2_3_pv
+        ,SUM(CAST(c2_3_exp AS BIGINT))                                                    AS c2_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_3_rov
+        ,SUM(CAST(c3_3_uv AS BIGINT))                                                     AS c3_3_uv
+        ,SUM(CAST(c3_3_pv AS BIGINT))                                                     AS c3_3_pv
+        ,SUM(CAST(c3_3_exp AS BIGINT))                                                    AS c3_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_3_rov
+
+        -- ==================== D链 (全量depth, 按hop) ====================
+        ,SUM(CAST(d0 AS BIGINT))                                                        AS d0
+        ,SUM(CAST(dn_1_uv AS BIGINT))                                                   AS dn_1_uv
+        ,SUM(CAST(dn_1_pv AS BIGINT))                                                   AS dn_1_pv
+        ,SUM(CAST(dn_1_exp AS BIGINT))                                                  AS dn_1_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS dn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS dn_1_rov
+        ,SUM(CAST(dn_2_uv AS BIGINT))                                                   AS dn_2_uv
+        ,SUM(CAST(dn_2_pv AS BIGINT))                                                   AS dn_2_pv
+        ,SUM(CAST(dn_2_exp AS BIGINT))                                                  AS dn_2_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_2_rov
+        ,SUM(CAST(dn_3_uv AS BIGINT))                                                   AS dn_3_uv
+        ,SUM(CAST(dn_3_pv AS BIGINT))                                                   AS dn_3_pv
+        ,SUM(CAST(dn_3_exp AS BIGINT))                                                  AS dn_3_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_3_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_3_rov
+        ,SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))  AS dn_total_uv
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_rov
+
+        -- ==================== D链 (按depth拆分) ====================
+        -- hop1
+        ,SUM(CAST(d1_1_uv AS BIGINT))                                                     AS d1_1_uv
+        ,SUM(CAST(d1_1_pv AS BIGINT))                                                     AS d1_1_pv
+        ,SUM(CAST(d1_1_exp AS BIGINT))                                                    AS d1_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS d1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS d1_1_rov
+        ,SUM(CAST(d2_1_uv AS BIGINT))                                                     AS d2_1_uv
+        ,SUM(CAST(d2_1_pv AS BIGINT))                                                     AS d2_1_pv
+        ,SUM(CAST(d2_1_exp AS BIGINT))                                                    AS d2_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_1_rov
+        ,SUM(CAST(d3_1_uv AS BIGINT))                                                     AS d3_1_uv
+        ,SUM(CAST(d3_1_pv AS BIGINT))                                                     AS d3_1_pv
+        ,SUM(CAST(d3_1_exp AS BIGINT))                                                    AS d3_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_1_rov
+        -- hop2
+        ,SUM(CAST(d1_2_uv AS BIGINT))                                                     AS d1_2_uv
+        ,SUM(CAST(d1_2_pv AS BIGINT))                                                     AS d1_2_pv
+        ,SUM(CAST(d1_2_exp AS BIGINT))                                                    AS d1_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_2_rov
+        ,SUM(CAST(d2_2_uv AS BIGINT))                                                     AS d2_2_uv
+        ,SUM(CAST(d2_2_pv AS BIGINT))                                                     AS d2_2_pv
+        ,SUM(CAST(d2_2_exp AS BIGINT))                                                    AS d2_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_2_rov
+        ,SUM(CAST(d3_2_uv AS BIGINT))                                                     AS d3_2_uv
+        ,SUM(CAST(d3_2_pv AS BIGINT))                                                     AS d3_2_pv
+        ,SUM(CAST(d3_2_exp AS BIGINT))                                                    AS d3_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_2_rov
+        -- hop3
+        ,SUM(CAST(d1_3_uv AS BIGINT))                                                     AS d1_3_uv
+        ,SUM(CAST(d1_3_pv AS BIGINT))                                                     AS d1_3_pv
+        ,SUM(CAST(d1_3_exp AS BIGINT))                                                    AS d1_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_3_rov
+        ,SUM(CAST(d2_3_uv AS BIGINT))                                                     AS d2_3_uv
+        ,SUM(CAST(d2_3_pv AS BIGINT))                                                     AS d2_3_pv
+        ,SUM(CAST(d2_3_exp AS BIGINT))                                                    AS d2_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_3_rov
+        ,SUM(CAST(d3_3_uv AS BIGINT))                                                     AS d3_3_uv
+        ,SUM(CAST(d3_3_pv AS BIGINT))                                                     AS d3_3_pv
+        ,SUM(CAST(d3_3_exp AS BIGINT))                                                    AS d3_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_3_rov
+
+        -- ==================== 全链路 ====================
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))
+            + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+            + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+                                                                                        AS all_return_n_uv
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(COUNT(1), 0)
+        , 0), 6)                                                                        AS all_rovn
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_rov
+        ,ROUND(COALESCE(
+            (   SUM(CAST(return_n_uv_noself AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_ror
+
+
+-- =====================================================================
+-- FROM + GROUP BY CUBE
+-- =====================================================================
+
+FROM    t_wide
+
+GROUP BY CUBE(
+            user_type
+            ,hh_bucket
+            ,head_merge_leve2
+            ,vid_merge_leve2
+            ,vid_id
+        )
+
+ORDER BY exposure_cnt DESC
+;

+ 118 - 0
table_gen/tmp.md

@@ -0,0 +1,118 @@
+
+ 为 B/C/D/全链路的每个 _uv 级别添加:
+ - rov = 带回UV / 成本曝光数
+ - ror = 带回UV / 成本人数
+
+ 分母 = 该级别的输入来源(上一级的输出),hop 和 depth 都逐级递推。
+
+ 数据流 & 分母推导
+
+ 逐级传播逻辑
+
+ depth维度 (分享链深度, 逐级递推):
+   曝光 → share → depth=1点击(b1) → reshare → depth=2点击(b2) → reshare → depth=3点击(b3)
+
+ hop维度 (二次传播跳数, 逐级递推):
+   B chain output → [C hop1] → C hop1 output → [C hop2] → C hop2 output → [C hop3]
+
+ 完整分母映射
+ ┌─────────────────────┬─────────────────────┬─────────────────────┐
+ │        字段         │ rov 分母 (成本曝光) │ ror 分母 (成本人数) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ B链                 │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ bn (全量)           │ COUNT(1)            │ COUNT(DISTINCT mid) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ b1 (depth=1)        │ COUNT(1)            │ COUNT(DISTINCT mid) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ b2 (depth=2)        │ SUM(b1_exp)         │ SUM(b1_uv)          │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ b3 (depth=3)        │ SUM(b2_exp)         │ SUM(b2_uv)          │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ C链全量depth        │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ cn_1 (hop1)         │ SUM(bn_exp)         │ SUM(bn_uv)          │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ cn_2 (hop2)         │ SUM(cn_1_exp)       │ SUM(cn_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ cn_3 (hop3)         │ SUM(cn_2_exp)       │ SUM(cn_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ cn (合计)           │ SUM(bn_exp)         │ SUM(bn_uv)          │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ C链depth拆分 (hop1) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c1_1 (d1-hop1)      │ SUM(bn_exp)         │ SUM(bn_uv)          │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c2_1 (d2-hop1)      │ SUM(c1_1_exp)       │ SUM(c1_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c3_1 (d3-hop1)      │ SUM(c2_1_exp)       │ SUM(c2_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ C链depth拆分 (hop2) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c1_2 (d1-hop2)      │ SUM(cn_1_exp)       │ SUM(cn_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c2_2 (d2-hop2)      │ SUM(c1_2_exp)       │ SUM(c1_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c3_2 (d3-hop2)      │ SUM(c2_2_exp)       │ SUM(c2_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ C链depth拆分 (hop3) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c1_3 (d1-hop3)      │ SUM(cn_2_exp)       │ SUM(cn_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c2_3 (d2-hop3)      │ SUM(c1_3_exp)       │ SUM(c1_3_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ c3_3 (d3-hop3)      │ SUM(c2_3_exp)       │ SUM(c2_3_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ D链全量depth        │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ dn_1 (hop1)         │ SUM(d0)             │ COUNT(DISTINCT mid) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ dn_2 (hop2)         │ SUM(dn_1_exp)       │ SUM(dn_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ dn_3 (hop3)         │ SUM(dn_2_exp)       │ SUM(dn_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ dn (合计)           │ SUM(d0)             │ COUNT(DISTINCT mid) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ D链depth拆分 (hop1) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d1_1 (d1-hop1)      │ SUM(d0)             │ COUNT(DISTINCT mid) │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d2_1 (d2-hop1)      │ SUM(d1_1_exp)       │ SUM(d1_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d3_1 (d3-hop1)      │ SUM(d2_1_exp)       │ SUM(d2_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ D链depth拆分 (hop2) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d1_2 (d1-hop2)      │ SUM(dn_1_exp)       │ SUM(dn_1_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d2_2 (d2-hop2)      │ SUM(d1_2_exp)       │ SUM(d1_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d3_2 (d3-hop2)      │ SUM(d2_2_exp)       │ SUM(d2_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ D链depth拆分 (hop3) │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d1_3 (d1-hop3)      │ SUM(dn_2_exp)       │ SUM(dn_2_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d2_3 (d2-hop3)      │ SUM(d1_3_exp)       │ SUM(d1_3_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ d3_3 (d3-hop3)      │ SUM(d2_3_exp)       │ SUM(d2_3_uv)        │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ 全链路              │                     │                     │
+ ├─────────────────────┼─────────────────────┼─────────────────────┤
+ │ all                 │ COUNT(1)            │ COUNT(DISTINCT mid) │
+ └─────────────────────┴─────────────────────┴─────────────────────┘
+ 规则总结:
+ - depth 维度: depth=1 的成本=该hop的入口; depth=N+1 的成本=depth=N 的输出
+ - hop 维度: hop1 的成本=链路入口; hop N+1 的成本=hop N 全量depth的输出
+ - D链 hop1 没有独立的成本人数(d0是同一用户session内曝光), 用 exposure_uv
+
+ 实施步骤
+
+ 1. 输出 CSV 到 table_gen/rov_ror_fields.csv (61 字段的完整清单)
+ 2. DDL: 在 CREATE TABLE 每个链路块末尾追加 DOUBLE 字段
+ 3. SELECT: 追加 ROUND(COALESCE(numerator / NULLIF(denominator, 0), 0), 6)
+ 4. 验证: grep 计数确保 DDL 和 SELECT 字段数一致
+
+ 文件
+
+ - loghubods.dwd_recsys_alg_exposure_agg_wide_20260209.sql

+ 139 - 0
tasks/00_AB效果/02_推荐AB天级效果_对比对照组_ab.sql

@@ -0,0 +1,139 @@
+-- 推荐AB天级效果 - 含对照组对比
+-- 新增列:各指标相对对照组的变化率(lift)
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,CASE   WHEN apptype IN ("4") AND abcode IN ("ab0","ab1") THEN "实验组-先验地域降权"
+                    WHEN apptype IN ("4") AND abcode IN ("ab6","ab7") THEN "实验组-str+校准&ros-统计量"
+                    WHEN apptype IN ("4") AND abcode IN ("ab8","ab9") THEN "实验组-str+校准&ros损失函数优化"
+                    WHEN apptype IN ("4") AND abcode IN ("ab4","ab5") THEN "实验组-str+校准&ros天级更新"
+                    WHEN apptype IN ("4") AND abcode IN ("ab2","ab3") THEN "对照组"
+                    ELSE "其他"
+            END AS abcode
+            ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                    WHEN page IN ("回流页","其他") THEN "非推荐"
+                    ELSE "其他"
+            END AS page
+            ,mid
+            ,vid
+            ,is_share
+            ,share_cnt
+            ,is_return_1
+            ,is_return_n
+            ,is_return_noself
+            ,return_1_uv
+            ,return_n_uv
+            ,return_n_uv_noself
+            ,new_exposure_cnt
+            ,flowpool
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20250108
+    WHERE   dt = '${dt}'
+    AND     apptype IN ("4")
+    AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+    AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+    AND     abcode NOT IN ("ab100")
+),
+-- 计算各组基础指标
+t_metrics AS (
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,page
+            ,COUNT(1) / COUNT(DISTINCT mid) AS exp_per_dau
+            ,SUM(is_share) / COUNT(1) AS str_one
+            ,SUM(return_n_uv) / SUM(is_share) AS ros_one
+            ,SUM(share_cnt) / COUNT(1) AS str
+            ,SUM(return_n_uv) / SUM(share_cnt) AS ros
+            ,SUM(is_return_1) / COUNT(1) AS str_plus
+            ,SUM(return_n_uv) / SUM(is_return_1) AS ros_minus
+            ,SUM(return_n_uv) / COUNT(1) AS rovn
+            ,SUM(new_exposure_cnt) / COUNT(1) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            ,COALESCE(SUM(is_share),0) AS is_share
+            ,COALESCE(SUM(share_cnt),0) AS share_cnt
+            ,COALESCE(SUM(is_return_1),0) AS is_return_1
+            ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+            ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+            ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+    FROM    t_base
+    WHERE   page IN ("推荐")
+    GROUP BY dt
+             ,apptype
+             ,abcode
+             ,page
+),
+-- 获取对照组数据
+t_control AS (
+    SELECT  dt
+            ,apptype
+            ,page
+            ,exp_per_dau AS ctrl_exp_per_dau
+            ,str_one AS ctrl_str_one
+            ,ros_one AS ctrl_ros_one
+            ,str AS ctrl_str
+            ,ros AS ctrl_ros
+            ,str_plus AS ctrl_str_plus
+            ,ros_minus AS ctrl_ros_minus
+            ,rovn AS ctrl_rovn
+            ,vovh24 AS ctrl_vovh24
+            ,dau AS ctrl_dau
+            ,exp AS ctrl_exp
+            ,is_share AS ctrl_is_share
+            ,share_cnt AS ctrl_share_cnt
+            ,is_return_1 AS ctrl_is_return_1
+            ,return_n_uv AS ctrl_return_n_uv
+            ,viewh24 AS ctrl_viewh24
+            ,return_n_uv_noself AS ctrl_return_n_uv_noself
+    FROM    t_metrics
+    WHERE   abcode = "对照组"
+)
+-- 关联对照组,计算变化率
+SELECT  m.dt
+        ,m.apptype
+        ,m.abcode
+        ,m.page
+        -- 原始指标
+        ,m.exp_per_dau
+        ,m.str_one
+        ,m.ros_one
+        ,m.str
+        ,m.ros
+        ,m.str_plus
+        ,m.ros_minus
+        ,m.rovn
+        ,m.vovh24
+        ,m.dau
+        ,m.exp
+        ,m.is_share
+        ,m.share_cnt
+        ,m.is_return_1
+        ,m.return_n_uv
+        ,m.viewh24
+        ,m.return_n_uv_noself
+        -- 相对对照组变化率
+        ,(m.exp_per_dau - c.ctrl_exp_per_dau) / c.ctrl_exp_per_dau AS exp_per_dau_lift
+        ,(m.str_one - c.ctrl_str_one) / c.ctrl_str_one AS str_one_lift
+        ,(m.ros_one - c.ctrl_ros_one) / c.ctrl_ros_one AS ros_one_lift
+        ,(m.str - c.ctrl_str) / c.ctrl_str AS str_lift
+        ,(m.ros - c.ctrl_ros) / c.ctrl_ros AS ros_lift
+        ,(m.str_plus - c.ctrl_str_plus) / c.ctrl_str_plus AS str_plus_lift
+        ,(m.ros_minus - c.ctrl_ros_minus) / c.ctrl_ros_minus AS ros_minus_lift
+        ,(m.rovn - c.ctrl_rovn) / c.ctrl_rovn AS rovn_lift
+        ,(m.vovh24 - c.ctrl_vovh24) / c.ctrl_vovh24 AS vovh24_lift
+        ,(m.dau - c.ctrl_dau) / c.ctrl_dau AS dau_lift
+        ,(m.exp - c.ctrl_exp) / c.ctrl_exp AS exp_lift
+        ,(m.is_share - c.ctrl_is_share) / c.ctrl_is_share AS is_share_lift
+        ,(m.share_cnt - c.ctrl_share_cnt) / c.ctrl_share_cnt AS share_cnt_lift
+        ,(m.is_return_1 - c.ctrl_is_return_1) / c.ctrl_is_return_1 AS is_return_1_lift
+        ,(m.return_n_uv - c.ctrl_return_n_uv) / c.ctrl_return_n_uv AS return_n_uv_lift
+        ,(m.viewh24 - c.ctrl_viewh24) / c.ctrl_viewh24 AS viewh24_lift
+        ,(m.return_n_uv_noself - c.ctrl_return_n_uv_noself) / c.ctrl_return_n_uv_noself AS return_n_uv_noself_lift
+FROM    t_metrics m
+LEFT JOIN t_control c
+ON      m.dt = c.dt
+AND     m.apptype = c.apptype
+AND     m.page = c.page
+ORDER BY m.dt DESC, m.apptype, m.page, m.abcode
+;

+ 6 - 0
tasks/00_AB效果/02_推荐AB天级效果_对比对照组_分ab.json

@@ -0,0 +1,6 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "wblMdQ",
+  "sort": "dt:desc",
+  "cols": null
+}

+ 140 - 0
tasks/00_AB效果/02_推荐AB天级效果_对比对照组_分ab.sql

@@ -0,0 +1,140 @@
+-- 推荐AB天级效果 - 含对照组对比
+-- 新增列:各指标相对对照组的变化率(lift)
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,concat(abcode, "-", CASE
+                    WHEN apptype IN ("4") AND abcode IN ("ab0", "ab1") THEN "实验组-先验地域降权"
+                    WHEN apptype IN ("4") AND abcode IN ("ab6") THEN "实验组-str校准&ros-统计量"
+                    WHEN apptype IN ("4") AND abcode IN ("ab8") THEN "实验组-str校准&ros损失函数优化"
+                    WHEN apptype IN ("4") AND abcode IN ("ab4") THEN "实验组-str校准&ros天级更新"
+                    WHEN apptype IN ("4") AND abcode IN ("ab2", "ab3") THEN "对照组"
+                    ELSE "对照组"
+            END) AS abcode
+            ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                    WHEN page IN ("回流页","其他") THEN "非推荐"
+                    ELSE "其他"
+            END AS page
+            ,mid
+            ,vid
+            ,is_share
+            ,share_cnt
+            ,is_return_1
+            ,is_return_n
+            ,is_return_noself
+            ,return_1_uv
+            ,return_n_uv
+            ,return_n_uv_noself
+            ,new_exposure_cnt
+            ,flowpool
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20250108
+    WHERE   dt = '${dt}'
+    AND     apptype IN ("4")
+    AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+    AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+    AND     abcode NOT IN ("ab100")
+),
+-- 计算各组基础指标
+t_metrics AS (
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,page
+            ,COUNT(1) / COUNT(DISTINCT mid) AS exp_per_dau
+            ,SUM(is_share) / COUNT(1) AS str_one
+            ,SUM(return_n_uv) / SUM(is_share) AS ros_one
+            ,SUM(share_cnt) / COUNT(1) AS str
+            ,SUM(return_n_uv) / SUM(share_cnt) AS ros
+            ,SUM(is_return_1) / COUNT(1) AS str_plus
+            ,SUM(return_n_uv) / SUM(is_return_1) AS ros_minus
+            ,SUM(return_n_uv) / COUNT(1) AS rovn
+            ,SUM(new_exposure_cnt) / COUNT(1) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            ,COALESCE(SUM(is_share),0) AS is_share
+            ,COALESCE(SUM(share_cnt),0) AS share_cnt
+            ,COALESCE(SUM(is_return_1),0) AS is_return_1
+            ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+            ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+            ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+    FROM    t_base
+    WHERE   page IN ("推荐")
+    GROUP BY dt
+             ,apptype
+             ,abcode
+             ,page
+),
+-- 获取对照组数据
+t_control AS (
+    SELECT  dt
+            ,apptype
+            ,page
+            ,exp_per_dau AS ctrl_exp_per_dau
+            ,str_one AS ctrl_str_one
+            ,ros_one AS ctrl_ros_one
+            ,str AS ctrl_str
+            ,ros AS ctrl_ros
+            ,str_plus AS ctrl_str_plus
+            ,ros_minus AS ctrl_ros_minus
+            ,rovn AS ctrl_rovn
+            ,vovh24 AS ctrl_vovh24
+            ,dau AS ctrl_dau
+            ,exp AS ctrl_exp
+            ,is_share AS ctrl_is_share
+            ,share_cnt AS ctrl_share_cnt
+            ,is_return_1 AS ctrl_is_return_1
+            ,return_n_uv AS ctrl_return_n_uv
+            ,viewh24 AS ctrl_viewh24
+            ,return_n_uv_noself AS ctrl_return_n_uv_noself
+    FROM    t_metrics
+    WHERE   abcode = "ab2-对照组"
+)
+-- 关联对照组,计算变化率
+SELECT  m.dt
+        ,m.apptype
+        ,m.abcode
+        ,m.page
+        -- 原始指标
+        ,m.exp_per_dau
+        ,m.str_one
+        ,m.ros_one
+        ,m.str
+        ,m.ros
+        ,m.str_plus
+        ,m.ros_minus
+        ,m.rovn
+        ,m.vovh24
+        ,m.dau
+        ,m.exp
+        ,m.is_share
+        ,m.share_cnt
+        ,m.is_return_1
+        ,m.return_n_uv
+        ,m.viewh24
+        ,m.return_n_uv_noself
+        -- 相对对照组变化率
+        ,(m.exp_per_dau - c.ctrl_exp_per_dau) / c.ctrl_exp_per_dau AS exp_per_dau_lift
+        ,(m.str_one - c.ctrl_str_one) / c.ctrl_str_one AS str_one_lift
+        ,(m.ros_one - c.ctrl_ros_one) / c.ctrl_ros_one AS ros_one_lift
+        ,(m.str - c.ctrl_str) / c.ctrl_str AS str_lift
+        ,(m.ros - c.ctrl_ros) / c.ctrl_ros AS ros_lift
+        ,(m.str_plus - c.ctrl_str_plus) / c.ctrl_str_plus AS str_plus_lift
+        ,(m.ros_minus - c.ctrl_ros_minus) / c.ctrl_ros_minus AS ros_minus_lift
+        ,(m.rovn - c.ctrl_rovn) / c.ctrl_rovn AS rovn_lift
+        ,(m.vovh24 - c.ctrl_vovh24) / c.ctrl_vovh24 AS vovh24_lift
+        ,(m.dau - c.ctrl_dau) / c.ctrl_dau AS dau_lift
+        ,(m.exp - c.ctrl_exp) / c.ctrl_exp AS exp_lift
+        ,(m.is_share - c.ctrl_is_share) / c.ctrl_is_share AS is_share_lift
+        ,(m.share_cnt - c.ctrl_share_cnt) / c.ctrl_share_cnt AS share_cnt_lift
+        ,(m.is_return_1 - c.ctrl_is_return_1) / c.ctrl_is_return_1 AS is_return_1_lift
+        ,(m.return_n_uv - c.ctrl_return_n_uv) / c.ctrl_return_n_uv AS return_n_uv_lift
+        ,(m.viewh24 - c.ctrl_viewh24) / c.ctrl_viewh24 AS viewh24_lift
+        ,(m.return_n_uv_noself - c.ctrl_return_n_uv_noself) / c.ctrl_return_n_uv_noself AS return_n_uv_noself_lift
+FROM    t_metrics m
+LEFT JOIN t_control c
+ON      m.dt = c.dt
+AND     m.apptype = c.apptype
+AND     m.page = c.page
+ORDER BY m.dt DESC, m.apptype, m.page, m.abcode
+;

+ 195 - 0
tasks/00_AB效果/05_推荐AB天级效果_对比对照组_含多跳_v2.sql

@@ -0,0 +1,195 @@
+-- 推荐AB天级效果 - 含对照组对比 + 多跳B/C/D指标
+-- 基于新表 dwd_recsys_alg_exposure_base_20260206,新增 b/c_1~c_3/d_1~d_3/total_bc/total_d/total_bcd per-exposure 率指标
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,CASE   WHEN apptype IN ("4") AND abcode IN ("ab1") THEN "实验组-先验地域降权aa"
+                    WHEN apptype IN ("4") AND abcode IN ("ab0") THEN "实验组-先验地域降权"
+                    WHEN apptype IN ("4") AND abcode IN ("ab7") THEN "实验组-str+校准&ros-统计量aa"
+                    WHEN apptype IN ("4") AND abcode IN ("ab6") THEN "实验组-str+校准&ros-统计量"
+                    WHEN apptype IN ("4") AND abcode IN ("ab9") THEN "实验组-str+校准&ros损失函数优化aa"
+                    WHEN apptype IN ("4") AND abcode IN ("ab8") THEN "实验组-str+校准&ros损失函数优化"
+                    WHEN apptype IN ("4") AND abcode IN ("ab5") THEN "实验组-str+校准&ros天级更新aa"
+                    WHEN apptype IN ("4") AND abcode IN ("ab4") THEN "实验组-str+校准&ros天级更新"
+                    WHEN apptype IN ("4") AND abcode IN ("ab3") THEN "对照组aa"
+                    WHEN apptype IN ("4") AND abcode IN ("ab2") THEN "对照组"
+                    ELSE "其他"
+            END AS abcode
+            ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                    WHEN page IN ("回流页","其他") THEN "非推荐"
+                    ELSE "其他"
+            END AS page
+            ,mid
+            ,vid
+            ,is_share
+            ,share_cnt
+            ,is_return_1
+            ,is_return_n
+            ,is_return_noself
+            ,return_1_uv
+            ,return_n_uv
+            ,return_n_uv_noself
+            ,new_exposure_cnt
+            ,flowpool
+            ,COALESCE(CAST(b AS BIGINT), 0) AS b
+            ,COALESCE(CAST(c_1 AS BIGINT), 0) AS c_1
+            ,COALESCE(CAST(c_2 AS BIGINT), 0) AS c_2
+            ,COALESCE(CAST(c_3 AS BIGINT), 0) AS c_3
+            ,COALESCE(CAST(d_1 AS BIGINT), 0) AS d_1
+            ,COALESCE(CAST(d_2 AS BIGINT), 0) AS d_2
+            ,COALESCE(CAST(d_3 AS BIGINT), 0) AS d_3
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260206
+    WHERE   dt = '${dt}'
+    AND     apptype IN ("4")
+    AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+    AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+    AND     abcode NOT IN ("ab100")
+),
+-- 计算各组基础指标
+t_metrics AS (
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,page
+            ,COUNT(1) / COUNT(DISTINCT mid) AS exp_per_dau
+            ,SUM(is_share) / COUNT(1) AS str_one
+            ,SUM(return_n_uv) / SUM(is_share) AS ros_one
+            ,SUM(share_cnt) / COUNT(1) AS str
+            ,SUM(return_n_uv) / SUM(share_cnt) AS ros
+            ,SUM(is_return_1) / COUNT(1) AS str_plus
+            ,SUM(return_n_uv) / SUM(is_return_1) AS ros_minus
+            ,SUM(return_n_uv) / COUNT(1) AS rovn
+            ,SUM(new_exposure_cnt) / COUNT(1) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            ,COALESCE(SUM(is_share),0) AS is_share
+            ,COALESCE(SUM(share_cnt),0) AS share_cnt
+            ,COALESCE(SUM(is_return_1),0) AS is_return_1
+            ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+            ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+            ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+            ,SUM(b) / COUNT(1) AS b
+            ,SUM(c_1) / COUNT(1) AS c_1
+            ,SUM(c_2) / COUNT(1) AS c_2
+            ,SUM(c_3) / COUNT(1) AS c_3
+            ,SUM(b + c_1 + c_2 + c_3) / COUNT(1) AS total_bc
+            ,SUM(d_1) / COUNT(1) AS d_1
+            ,SUM(d_2) / COUNT(1) AS d_2
+            ,SUM(d_3) / COUNT(1) AS d_3
+            ,SUM(d_1 + d_2 + d_3) / COUNT(1) AS total_d
+            ,SUM(b + c_1 + c_2 + c_3 + d_1 + d_2 + d_3) / COUNT(1) AS total_bcd
+            ,SUM(b + c_1 + c_2 + c_3 + d_1) / COUNT(1) AS total_bcd1
+    FROM    t_base
+    WHERE   page IN ("推荐")
+    GROUP BY dt
+             ,apptype
+             ,abcode
+             ,page
+),
+-- 获取对照组数据
+t_control AS (
+    SELECT  dt
+            ,apptype
+            ,page
+            ,exp_per_dau AS ctrl_exp_per_dau
+            ,str_one AS ctrl_str_one
+            ,ros_one AS ctrl_ros_one
+            ,str AS ctrl_str
+            ,ros AS ctrl_ros
+            ,str_plus AS ctrl_str_plus
+            ,ros_minus AS ctrl_ros_minus
+            ,rovn AS ctrl_rovn
+            ,vovh24 AS ctrl_vovh24
+            ,dau AS ctrl_dau
+            ,exp AS ctrl_exp
+            ,is_share AS ctrl_is_share
+            ,share_cnt AS ctrl_share_cnt
+            ,is_return_1 AS ctrl_is_return_1
+            ,return_n_uv AS ctrl_return_n_uv
+            ,viewh24 AS ctrl_viewh24
+            ,return_n_uv_noself AS ctrl_return_n_uv_noself
+            ,b AS ctrl_b
+            ,c_1 AS ctrl_c_1
+            ,c_2 AS ctrl_c_2
+            ,c_3 AS ctrl_c_3
+            ,total_bc AS ctrl_total_bc
+            ,d_1 AS ctrl_d_1
+            ,d_2 AS ctrl_d_2
+            ,d_3 AS ctrl_d_3
+            ,total_d AS ctrl_total_d
+            ,total_bcd AS ctrl_total_bcd
+            ,total_bcd1 AS ctrl_total_bcd1
+    FROM    t_metrics
+    WHERE   abcode = "对照组"
+)
+-- 关联对照组,计算变化率
+SELECT  m.dt
+        ,m.apptype
+        ,m.abcode
+        ,m.page
+        -- 原始指标
+        ,m.exp_per_dau
+        ,m.str_one
+        ,m.ros_one
+        ,m.str
+        ,m.ros
+        ,m.str_plus
+        ,m.ros_minus
+        ,m.rovn
+        ,m.vovh24
+        ,m.dau
+        ,m.exp
+        ,m.is_share
+        ,m.share_cnt
+        ,m.is_return_1
+        ,m.return_n_uv
+        ,m.viewh24
+        ,m.return_n_uv_noself
+        ,m.b
+        ,m.c_1
+        ,m.c_2
+        ,m.c_3
+        ,m.total_bc
+        ,m.d_1
+        ,m.d_2
+        ,m.d_3
+        ,m.total_d
+        ,m.total_bcd
+        ,m.total_bcd1
+        -- 相对对照组变化率
+        ,(m.exp_per_dau - c.ctrl_exp_per_dau) / c.ctrl_exp_per_dau AS exp_per_dau_lift
+        ,(m.str_one - c.ctrl_str_one) / c.ctrl_str_one AS str_one_lift
+        ,(m.ros_one - c.ctrl_ros_one) / c.ctrl_ros_one AS ros_one_lift
+        ,(m.str - c.ctrl_str) / c.ctrl_str AS str_lift
+        ,(m.ros - c.ctrl_ros) / c.ctrl_ros AS ros_lift
+        ,(m.str_plus - c.ctrl_str_plus) / c.ctrl_str_plus AS str_plus_lift
+        ,(m.ros_minus - c.ctrl_ros_minus) / c.ctrl_ros_minus AS ros_minus_lift
+        ,(m.rovn - c.ctrl_rovn) / c.ctrl_rovn AS rovn_lift
+        ,(m.vovh24 - c.ctrl_vovh24) / c.ctrl_vovh24 AS vovh24_lift
+        ,(m.dau - c.ctrl_dau) / c.ctrl_dau AS dau_lift
+        ,(m.exp - c.ctrl_exp) / c.ctrl_exp AS exp_lift
+        ,(m.is_share - c.ctrl_is_share) / c.ctrl_is_share AS is_share_lift
+        ,(m.share_cnt - c.ctrl_share_cnt) / c.ctrl_share_cnt AS share_cnt_lift
+        ,(m.is_return_1 - c.ctrl_is_return_1) / c.ctrl_is_return_1 AS is_return_1_lift
+        ,(m.return_n_uv - c.ctrl_return_n_uv) / c.ctrl_return_n_uv AS return_n_uv_lift
+        ,(m.viewh24 - c.ctrl_viewh24) / c.ctrl_viewh24 AS viewh24_lift
+        ,(m.return_n_uv_noself - c.ctrl_return_n_uv_noself) / c.ctrl_return_n_uv_noself AS return_n_uv_noself_lift
+        ,(m.b - c.ctrl_b) / c.ctrl_b AS b_lift
+        ,(m.c_1 - c.ctrl_c_1) / c.ctrl_c_1 AS c_1_lift
+        ,(m.c_2 - c.ctrl_c_2) / c.ctrl_c_2 AS c_2_lift
+        ,(m.c_3 - c.ctrl_c_3) / c.ctrl_c_3 AS c_3_lift
+        ,(m.total_bc - c.ctrl_total_bc) / c.ctrl_total_bc AS total_bc_lift
+        ,(m.d_1 - c.ctrl_d_1) / c.ctrl_d_1 AS d_1_lift
+        ,(m.d_2 - c.ctrl_d_2) / c.ctrl_d_2 AS d_2_lift
+        ,(m.d_3 - c.ctrl_d_3) / c.ctrl_d_3 AS d_3_lift
+        ,(m.total_d - c.ctrl_total_d) / c.ctrl_total_d AS total_d_lift
+        ,(m.total_bcd - c.ctrl_total_bcd) / c.ctrl_total_bcd AS total_bcd_lift
+        ,(m.total_bcd1 - c.ctrl_total_bcd1) / c.ctrl_total_bcd1 AS total_bcd1_lift
+FROM    t_metrics m
+LEFT JOIN t_control c
+ON      m.dt = c.dt
+AND     m.apptype = c.apptype
+AND     m.page = c.page
+ORDER BY m.dt DESC, m.apptype, m.page, m.abcode
+;

+ 7 - 0
tasks/00_尾号实验/base.json

@@ -0,0 +1,7 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "pvHZPg",
+  "sort": "dt:desc",
+  "cols": null,
+  "filter": "abcode!=other"
+}

+ 123 - 0
tasks/00_尾号实验/base.sql

@@ -0,0 +1,123 @@
+WITH t_abmap AS
+(
+    SELECT "1" AS suffix, "实验组:str校准 & ros天级更新" AS abcode
+    UNION ALL SELECT "2", "实验组:str校准 & ros统计量"
+    UNION ALL SELECT "3", "实验组:ros损失函数优化"
+    UNION ALL SELECT "a", "对照组"
+    UNION ALL SELECT "b", "对照组"
+    UNION ALL SELECT "c", "对照组"
+    UNION ALL SELECT "d", "对照组"
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,COALESCE(m.abcode,"other") AS abcode
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'),LENGTH(GET_JSON_OBJECT(extend,'$.rootsessionid')),1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,mid
+                        ,vid
+                        ,is_share
+                        ,share_cnt
+                        ,is_return_1
+                        ,is_return_n
+                        ,is_return_noself
+                        ,return_1_uv
+                        ,return_n_uv
+                        ,return_n_uv_noself
+                        ,new_exposure_cnt
+                        ,flowpool
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108
+                WHERE   dt="${dt}"
+                AND     apptype IN ("4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+)
+,t_dau2 AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"other") AS abcode
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),1) AS suffix
+                FROM    loghubods.useractive_log
+                WHERE   dt="${dt}"
+                -- FROM    loghubods.useractive_log_per5min
+                -- WHERE   dt BETWEEN CONCAT("${dt}","000000") AND CONCAT("${dt}","235500")
+                AND     apptype IN ("4")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+    GROUP BY SUBSTR(sub.dt,1,8)
+             ,sub.apptype
+             ,COALESCE(m.abcode,"other")
+)
+SELECT  a.dt
+        ,a.apptype
+        ,a.abcode
+        ,a.exp_per_dau
+        ,a.str_one
+        ,a.ros_one
+        ,a.str
+        ,a.ros
+        ,a.str_plus
+        ,a.ros_minus
+        ,a.rovn
+        ,a.vovh24
+        ,a.dau
+        ,a.exp
+        ,a.is_share
+        ,a.share_cnt
+        ,a.is_return_1
+        ,a.return_n_uv
+        ,a.viewh24
+        ,a.return_n_uv_noself
+        ,b.dau2
+FROM    (
+            SELECT  dt
+                    ,apptype
+                    ,abcode
+                    ,round(COALESCE(COUNT(1) / COUNT(DISTINCT mid),0),2) AS exp_per_dau
+                    ,round(COALESCE(SUM(is_share) / COUNT(1),0),6) AS str_one
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_share),0),6) AS ros_one
+                    ,round(COALESCE(SUM(share_cnt) / COUNT(1),0),6) AS str
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(share_cnt),0),6) AS ros
+                    ,round(COALESCE(SUM(is_return_1) / COUNT(1),0),6) AS str_plus
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_return_1),0),6) AS ros_minus
+                    ,round(COALESCE(SUM(return_n_uv) / COUNT(1),0),6) AS rovn
+                    ,round(COALESCE(SUM(new_exposure_cnt) / COUNT(1),0),6) AS vovh24
+                    ,COUNT(DISTINCT mid) AS dau
+                    ,COUNT(1) AS exp
+                    ,COALESCE(SUM(is_share),0) AS is_share
+                    ,COALESCE(SUM(share_cnt),0) AS share_cnt
+                    ,COALESCE(SUM(is_return_1),0) AS is_return_1
+                    ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+                    ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+                    ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+            FROM    t_base
+            WHERE   page = "推荐"
+            GROUP BY dt
+                     ,apptype
+                     ,abcode
+        ) a
+LEFT JOIN t_dau2 b
+ON      a.dt = b.dt
+AND     a.apptype = b.apptype
+AND     a.abcode = b.abcode
+ORDER BY a.dt DESC,a.apptype,a.abcode
+;

+ 7 - 0
tasks/00_尾号实验/base_v1.json

@@ -0,0 +1,7 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "K5XBxy",
+  "sort": "dt:desc",
+  "cols": null,
+  "filter": "abcode!=other"
+}

+ 122 - 0
tasks/00_尾号实验/base_v1.sql

@@ -0,0 +1,122 @@
+WITH t_abmap AS
+(
+    SELECT "1" AS suffix, "实验组:str校准 & ros天级更新" AS abcode
+    UNION ALL SELECT "2", "实验组:str校准 & ros统计量"
+    UNION ALL SELECT "3", "实验组:ros损失函数优化"
+    UNION ALL SELECT "4", "实验组:c1_rovn & 去掉vor实验"
+    UNION ALL SELECT "5", "实验组:b0_str & 去掉vor实验"
+    UNION ALL SELECT "c", "对照组"
+    UNION ALL SELECT "d", "对照组"
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,COALESCE(m.abcode,"other") AS abcode
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'),LENGTH(GET_JSON_OBJECT(extend,'$.rootsessionid')),1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,mid
+                        ,vid
+                        ,is_share
+                        ,share_cnt
+                        ,is_return_1
+                        ,is_return_n
+                        ,is_return_noself
+                        ,return_1_uv
+                        ,return_n_uv
+                        ,return_n_uv_noself
+                        ,new_exposure_cnt
+                        ,flowpool
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108
+                WHERE   dt ="${dt}"
+                -- and hh between "21" and "24"
+                AND     apptype IN ("4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+)
+,t_dau2 AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"other") AS abcode
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),1) AS suffix
+                FROM    loghubods.useractive_log_per5min
+                WHERE   dt BETWEEN CONCAT("${dt}","000000") AND CONCAT("${dt}","239999")
+                AND     apptype IN ("4")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+    GROUP BY SUBSTR(sub.dt,1,8)
+             ,sub.apptype
+             ,COALESCE(m.abcode,"other")
+)
+SELECT  a.dt
+        ,a.apptype
+        ,a.abcode
+        ,a.exp_per_dau
+        ,a.str_one
+        ,a.ros_one
+        ,a.str
+        ,a.ros
+        ,a.str_plus
+        ,a.ros_minus
+        ,a.rovn
+        ,a.vovh24
+        ,a.dau
+        ,a.exp
+        ,a.is_share
+        ,a.share_cnt
+        ,a.is_return_1
+        ,a.return_n_uv
+        ,a.viewh24
+        ,a.return_n_uv_noself
+        ,b.dau2
+FROM    (
+            SELECT  dt
+                    ,apptype
+                    ,abcode
+                    ,round(COALESCE(COUNT(1) / COUNT(DISTINCT mid),0),2) AS exp_per_dau
+                    ,round(COALESCE(SUM(is_share) / COUNT(1),0),6) AS str_one
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_share),0),6) AS ros_one
+                    ,round(COALESCE(SUM(share_cnt) / COUNT(1),0),6) AS str
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(share_cnt),0),6) AS ros
+                    ,round(COALESCE(SUM(is_return_1) / COUNT(1),0),6) AS str_plus
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_return_1),0),6) AS ros_minus
+                    ,round(COALESCE(SUM(return_n_uv) / COUNT(1),0),6) AS rovn
+                    ,round(COALESCE(SUM(new_exposure_cnt) / COUNT(1),0),6) AS vovh24
+                    ,COUNT(DISTINCT mid) AS dau
+                    ,COUNT(1) AS exp
+                    ,COALESCE(SUM(is_share),0) AS is_share
+                    ,COALESCE(SUM(share_cnt),0) AS share_cnt
+                    ,COALESCE(SUM(is_return_1),0) AS is_return_1
+                    ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+                    ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+                    ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+            FROM    t_base
+            WHERE   page = "推荐"
+            GROUP BY dt
+                     ,apptype
+                     ,abcode
+        ) a
+LEFT JOIN t_dau2 b
+ON      a.dt = b.dt
+AND     a.apptype = b.apptype
+AND     a.abcode = b.abcode
+ORDER BY a.dt DESC,a.apptype,a.abcode
+;

+ 7 - 0
tasks/00_尾号实验/base_v2.json

@@ -0,0 +1,7 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "pvHZPg",
+  "sort": "dt:desc",
+  "cols": null,
+  "filter": "abcode!=other,abcode!=6,abcode!=e,abcode!=f"
+}

+ 128 - 0
tasks/00_尾号实验/base_v2.sql

@@ -0,0 +1,128 @@
+WITH t_abmap AS
+(
+    SELECT "1" AS suffix, "实验组:str校准 & ros天级更新" AS abcode
+    UNION ALL SELECT "2", "实验组:str校准 & ros统计量"
+    UNION ALL SELECT "3", "实验组:ros损失函数优化"
+    UNION ALL SELECT "5", "实验组:b0_str & 去掉vor实验"
+    UNION ALL SELECT "4", "实验组:c1_rovn & 去掉vor实验"
+    UNION ALL SELECT "6", "6"
+    UNION ALL SELECT "e", "e"
+    UNION ALL SELECT "f", "f"
+    UNION ALL SELECT "a", "对照组"
+    UNION ALL SELECT "b", "对照组"
+    UNION ALL SELECT "c", "对照组"
+    UNION ALL SELECT "d", "对照组"
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,COALESCE(m.abcode,"other") AS abcode
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'),LENGTH(GET_JSON_OBJECT(extend,'$.rootsessionid')),1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,mid
+                        ,vid
+                        ,is_share
+                        ,share_cnt
+                        ,is_return_1
+                        ,is_return_n
+                        ,is_return_noself
+                        ,return_1_uv
+                        ,return_n_uv
+                        ,return_n_uv_noself
+                        ,new_exposure_cnt
+                        ,flowpool
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108
+                WHERE   dt="${dt}"
+                AND     apptype IN ("4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                AND     abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+)
+,t_dau2 AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"other") AS abcode
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),1) AS suffix
+                -- FROM    loghubods.useractive_log
+                -- WHERE   dt="${dt}"
+                FROM    loghubods.useractive_log_per5min
+                WHERE   dt BETWEEN CONCAT("${dt}","000000") AND CONCAT("${dt}","235500")
+                AND     apptype IN ("4")
+            ) sub
+    LEFT JOIN t_abmap m
+    ON      sub.apptype = "4"
+    AND     sub.suffix = m.suffix
+    GROUP BY SUBSTR(sub.dt,1,8)
+             ,sub.apptype
+             ,COALESCE(m.abcode,"other")
+)
+SELECT  a.dt
+        ,a.apptype
+        ,a.abcode
+        ,a.exp_per_dau
+        ,a.str_one
+        ,a.ros_one
+        ,a.str
+        ,a.ros
+        ,a.str_plus
+        ,a.ros_minus
+        ,a.rovn
+        ,a.vovh24
+        ,a.dau
+        ,a.exp
+        ,a.is_share
+        ,a.share_cnt
+        ,a.is_return_1
+        ,a.return_n_uv
+        ,a.viewh24
+        ,a.return_n_uv_noself
+        ,b.dau2
+FROM    (
+            SELECT  dt
+                    ,apptype
+                    ,abcode
+                    ,round(COALESCE(COUNT(1) / COUNT(DISTINCT mid),0),2) AS exp_per_dau
+                    ,round(COALESCE(SUM(is_share) / COUNT(1),0),6) AS str_one
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_share),0),6) AS ros_one
+                    ,round(COALESCE(SUM(share_cnt) / COUNT(1),0),6) AS str
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(share_cnt),0),6) AS ros
+                    ,round(COALESCE(SUM(is_return_1) / COUNT(1),0),6) AS str_plus
+                    ,round(COALESCE(SUM(return_n_uv) / SUM(is_return_1),0),6) AS ros_minus
+                    ,round(COALESCE(SUM(return_n_uv) / COUNT(1),0),6) AS rovn
+                    ,round(COALESCE(SUM(new_exposure_cnt) / COUNT(1),0),6) AS vovh24
+                    ,COUNT(DISTINCT mid) AS dau
+                    ,COUNT(1) AS exp
+                    ,COALESCE(SUM(is_share),0) AS is_share
+                    ,COALESCE(SUM(share_cnt),0) AS share_cnt
+                    ,COALESCE(SUM(is_return_1),0) AS is_return_1
+                    ,COALESCE(SUM(return_n_uv),0) AS return_n_uv
+                    ,COALESCE(SUM(new_exposure_cnt),0) AS viewh24
+                    ,COALESCE(SUM(return_n_uv_noself),0) AS return_n_uv_noself
+            FROM    t_base
+            WHERE   page = "推荐"
+            GROUP BY dt
+                     ,apptype
+                     ,abcode
+        ) a
+LEFT JOIN t_dau2 b
+ON      a.dt = b.dt
+AND     a.apptype = b.apptype
+AND     a.abcode = b.abcode
+ORDER BY a.dt DESC,a.apptype,a.abcode
+;

+ 28 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/05_click_top_from_mid.sql

@@ -0,0 +1,28 @@
+-- click 分享者(from_mid) top1000,按带回的 target_mid 人数降序
+-- from_mid = split(shareid, '-')[0],target_mid = machinecode(排除自点)
+-- 使用: python fetch_daily.py .../05_click_top_from_mid.sql --date 20260210
+
+SELECT dt, from_mid,
+       target_uv,
+       ROUND(target_uv * 100.0 / SUM(target_uv) OVER(PARTITION BY dt), 2) as target_uv_pct,
+       cnt,
+       vid,
+       max_depth, avg_depth
+FROM (
+    SELECT dt,
+           split(shareid, '-')[0] as from_mid,
+           COUNT(DISTINCT machinecode) as target_uv,
+           COUNT(1) as cnt,
+           COUNT(DISTINCT clickobjectid) as vid,
+           MAX(CAST(usersharedepth AS BIGINT)) as max_depth,
+           ROUND(AVG(CAST(usersharedepth AS BIGINT)), 2) as avg_depth,
+           ROW_NUMBER() OVER(PARTITION BY dt ORDER BY COUNT(DISTINCT machinecode) DESC) as rn
+    FROM loghubods.user_share_log
+    WHERE dt = '${dt}' AND topic = 'click'
+      AND split(shareid, '-')[0] <> machinecode  -- 排除自点
+      And rootsourceid = '' OR rootsourceid IS NULL  -- 排除转发带回的
+      And  
+    GROUP BY dt, split(shareid, '-')[0]
+) t
+WHERE rn <= 1000
+ORDER BY target_uv DESC

+ 29 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/06_活跃表概况.sql

@@ -0,0 +1,29 @@
+
+-- 活跃表 ods_user_active_log_info_day 基础概况
+-- 按 push_type / channel_type 分组统计 UV & CNT,对比 share_log click UV
+
+-- 1. 按 push_type 分组(含合计)
+SELECT dt, 'push_type' AS dim, COALESCE(push_type, '合计') AS val,
+       COUNT(DISTINCT machinecode) AS uv, COUNT(1) AS cnt
+FROM loghubods.ods_user_active_log_info_day
+WHERE dt = '${dt}'
+GROUP BY dt, push_type
+GROUPING SETS ((dt, push_type), (dt))
+
+UNION ALL
+
+-- 2. 按 channel_type 分组
+SELECT dt, 'channel_type' AS dim, channel_type AS val,
+       COUNT(DISTINCT machinecode) AS uv, COUNT(1) AS cnt
+FROM loghubods.ods_user_active_log_info_day
+WHERE dt = '${dt}'
+GROUP BY dt, channel_type
+
+UNION ALL
+
+-- 3. share_log click UV 做对比
+SELECT dt, 'share_log' AS dim, 'click_uv' AS val,
+       COUNT(DISTINCT machinecode) AS uv, COUNT(1) AS cnt
+FROM loghubods.user_share_log
+WHERE dt = '${dt}' AND topic = 'click'
+GROUP BY dt

+ 23 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/07_click_来源分布.sql

@@ -0,0 +1,23 @@
+
+-- share_log click 回流来源分布
+-- LEFT JOIN 活跃表,按 push_type + channel_type 分组
+
+SELECT  s.dt
+       ,COALESCE(a.push_type, '未匹配') AS push_type
+       ,COALESCE(a.channel_type, '未匹配') AS channel_type
+       ,COUNT(1) AS cnt
+       ,COUNT(DISTINCT s.machinecode) AS uv
+       ,COUNT(DISTINCT s.clickobjectid) AS vid_cnt
+       ,MAX(CAST(s.usersharedepth AS BIGINT)) AS max_depth
+       ,AVG(CAST(s.usersharedepth AS BIGINT)) AS avg_depth
+FROM loghubods.user_share_log s
+LEFT JOIN loghubods.ods_user_active_log_info_day a
+  ON  s.dt = a.dt
+  AND s.machinecode = a.machinecode
+  AND s.subsessionid = a.subsessionid
+WHERE s.dt = '${dt}'
+  AND s.topic = 'click'
+GROUP BY s.dt
+        ,COALESCE(a.push_type, '未匹配')
+        ,COALESCE(a.channel_type, '未匹配')
+ORDER BY cnt DESC

+ 25 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/08_click_level_channel分布.sql

@@ -0,0 +1,25 @@
+
+-- share_log click LEFT JOIN 活跃表
+-- 按 level_type / channel_type / channel_type_frist 分组看占比
+
+SELECT  s.dt
+       ,COALESCE(a.level_type, '未匹配') AS level_type
+       ,COALESCE(a.channel_type, '未匹配') AS channel_type
+       ,COALESCE(a.channel_type_frist, '未匹配') AS channel_type_frist
+       ,COUNT(1) AS cnt
+       ,ROUND(COUNT(1) * 100.0 / SUM(COUNT(1)) OVER(PARTITION BY s.dt), 2) AS cnt_pct
+       ,COUNT(DISTINCT s.machinecode) AS uv
+       ,ROUND(COUNT(DISTINCT s.machinecode) * 100.0
+              / SUM(COUNT(DISTINCT s.machinecode)) OVER(PARTITION BY s.dt), 2) AS uv_pct
+FROM loghubods.user_share_log s
+LEFT JOIN loghubods.ods_user_active_log_info_day a
+  ON  s.dt = a.dt
+  AND s.machinecode = a.machinecode
+  AND s.subsessionid = a.subsessionid
+WHERE s.dt = '${dt}'
+  AND s.topic = 'click'
+GROUP BY s.dt
+        ,COALESCE(a.level_type, '未匹配')
+        ,COALESCE(a.channel_type, '未匹配')
+        ,COALESCE(a.channel_type_frist, '未匹配')
+ORDER BY cnt DESC

+ 49 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/09_click_内外部_首层分布.sql

@@ -0,0 +1,49 @@
+
+-- click 按 内部/外部 + 外部首层/非外部首层 分布
+-- 内部判定: rootsourceid = '' OR rootsourceid IS NULL
+-- 外部首层判定: 复用 ods_user_active_log_info_day 的 level_type 逻辑
+
+WITH t9 AS (
+    SELECT  t1.root_source_id AS rootsourceid
+           ,t1.channel
+    FROM    loghubods.ad_put_flow_record_tencent_day t1
+    LEFT JOIN loghubods.content_platform_account t2
+    ON      t1.channel = t2.channel
+    WHERE   t1.dt = MAX_PT('loghubods.ad_put_flow_record_tencent_day')
+    AND     t1.put_type_one = '企微'
+    AND     t1.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_|dyycd_'
+    GROUP BY t1.root_source_id, t1.channel
+)
+
+SELECT dt,
+       COALESCE(source_type, '合计') AS source_type,
+       COALESCE(level_type, '合计') AS level_type,
+       COUNT(DISTINCT machinecode) AS uv, COUNT(1) AS cnt
+FROM (
+    SELECT s.dt, s.machinecode,
+           CASE WHEN s.rootsourceid = '' OR s.rootsourceid IS NULL
+                THEN '内部' ELSE '外部' END AS source_type,
+           CASE
+               WHEN s.rootsourceid = '' OR s.rootsourceid IS NULL
+                   THEN '内部'
+               WHEN s.rootsourceid REGEXP 'touliu_tencentwbqw_|dyyqw_'
+                   AND t9.channel REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss'
+                   AND CAST(s.usersharedepth AS BIGINT) <= 1
+                   THEN '外部首层'
+               WHEN s.rootsourceid REGEXP 'touliu_tencentwbqw_|dyyqw_'
+                   AND (t9.channel IS NULL OR t9.channel NOT REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss')
+                   AND CAST(s.usersharedepth AS BIGINT) = 0
+                   THEN '外部首层'
+               WHEN s.rootsourceid NOT REGEXP 'touliu_tencentwbqw_|dyyqw_'
+                   AND CAST(s.usersharedepth AS BIGINT) = 0
+                   THEN '外部首层'
+               ELSE '外部非首层'
+           END AS level_type
+    FROM loghubods.user_share_log s
+    LEFT JOIN t9
+    ON   s.rootsourceid = t9.rootsourceid
+    WHERE s.dt = '${dt}' AND s.topic = 'click'
+) t
+GROUP BY dt, source_type, level_type
+GROUPING SETS ((dt, source_type, level_type), (dt, source_type), (dt, level_type), (dt))
+ORDER BY source_type, level_type

+ 54 - 0
tasks/00_表的洞察/loghubods.user_share_log/00_洞察/10_click_top_from_mid_排除外部首层.sql

@@ -0,0 +1,54 @@
+
+-- click 排除外部首层后的 分享者(from_mid) top1000,按带回的 target_mid 人数降序
+-- 保留: 内部 + 外部非首层
+-- 使用: python fetch_daily.py .../10_click_top_from_mid_排除外部首层.sql --date 20260209
+
+WITH t9 AS (
+    SELECT  t1.root_source_id AS rootsourceid
+           ,t1.channel
+    FROM    loghubods.ad_put_flow_record_tencent_day t1
+    LEFT JOIN loghubods.content_platform_account t2
+    ON      t1.channel = t2.channel
+    WHERE   t1.dt = MAX_PT('loghubods.ad_put_flow_record_tencent_day')
+    AND     t1.put_type_one = '企微'
+    AND     t1.root_source_id REGEXP 'touliu_tencentwbqw_|dyyqw_|dyycd_'
+    GROUP BY t1.root_source_id, t1.channel
+)
+
+SELECT dt, from_mid,
+       target_uv,
+       ROUND(target_uv * 100.0 / SUM(target_uv) OVER(PARTITION BY dt), 2) as target_uv_pct,
+       cnt,
+       vid,
+       max_depth, avg_depth
+FROM (
+    SELECT s.dt,
+           split(s.shareid, '-')[0] as from_mid,
+           COUNT(DISTINCT s.machinecode) as target_uv,
+           COUNT(1) as cnt,
+           COUNT(DISTINCT s.clickobjectid) as vid,
+           MAX(CAST(s.usersharedepth AS BIGINT)) as max_depth,
+           ROUND(AVG(CAST(s.usersharedepth AS BIGINT)), 2) as avg_depth,
+           ROW_NUMBER() OVER(PARTITION BY s.dt ORDER BY COUNT(DISTINCT s.machinecode) DESC) as rn
+    FROM loghubods.user_share_log s
+    LEFT JOIN t9
+    ON   s.rootsourceid = t9.rootsourceid
+    WHERE s.dt = '${dt}' AND s.topic = 'click'
+      AND split(s.shareid, '-')[0] <> s.machinecode  -- 排除自点
+      -- 排除外部首层
+      AND NOT (
+          (s.rootsourceid REGEXP 'touliu_tencentwbqw_|dyyqw_'
+           AND t9.channel REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss'
+           AND CAST(s.usersharedepth AS BIGINT) <= 1)
+          OR
+          (s.rootsourceid REGEXP 'touliu_tencentwbqw_|dyyqw_'
+           AND (t9.channel IS NULL OR t9.channel NOT REGEXP 'xycsd|csaq|shy|jxjx|gzcr|xyjj|jxatm|xjcy|yqyx|hbwq|jxxm|gzmy|cdjh|gzjr|gzxts|twhc|qdjdz|sjzyd|gzyhc|djh|gzlx|yywl|szjn|gzdd1|cqqd|cqslh|hzjy|hzjh|sclh|xyhc|snss')
+           AND CAST(s.usersharedepth AS BIGINT) = 0)
+          OR
+          (s.rootsourceid NOT REGEXP 'touliu_tencentwbqw_|dyyqw_'
+           AND CAST(s.usersharedepth AS BIGINT) = 0)
+      )
+    GROUP BY s.dt, split(s.shareid, '-')[0]
+) t
+WHERE rn <= 1000
+ORDER BY target_uv DESC

+ 8 - 0
tasks/报表/01_推荐分发报表.json

@@ -0,0 +1,8 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "NRBX3k",
+  "sort": "dt:desc",
+  "filter": {"hh_bucket": "SUM"},
+  "limit": 40000,
+  "cols": null
+}

+ 678 - 0
tasks/报表/01_推荐分发报表.sql

@@ -0,0 +1,678 @@
+-- =====================================================================
+-- 曝光回流链路 CUBE 聚合表 (宽表版, 含用户/品类维度 + 模型预估 + 全链路漏斗)
+-- 维度: user_type × hh_bucket × head_merge_leve2 × vid_merge_leve2 × vid_id (CUBE)
+-- 依赖: base_20260209 → (JOIN user_type + video_merge_tag + t_score) → CUBE 聚合
+-- 参考: de.sql + dwd_recsys_alg_exposure_agg_20260209
+-- =====================================================================
+--
+-- 指标分区:
+--   基础流量       exposure_cnt / exposure_uv / vid_cnt / exposure_per_user
+--   分享&回流漏斗  share_exposure_cnt → share_cnt → return_exposure_cnt → return_uv
+--                  + 4 个 rate (share_rate / return_rate / return_rate_noself / share_return_rate)
+--   模型预估       STR (曝光→非自身回流概率) / ROSN (条件回流UV) / ROVN (STR×ROSN)
+--                  每组: _real(label) + _pred(预估) + _copc + _mae + _var
+--                  _real 与漏斗字段等价: str_real=return_rate_noself, rovn_real=return_uv_noself/exposure_cnt
+--   B/C/D 链       每级: _uv + _pv + _exp + _ror + _rov
+--   全链路         all_uv/pv/exp = B + C + D, all_ror/rov
+--
+-- rov/ror 分母推导 (逐级递推):
+--   depth 维度: depth=1 的成本=该hop入口; depth=N+1 的成本=depth=N 的输出
+--   hop 维度:   hop1 的成本=链路入口; hop N+1 的成本=hop N 全量depth的输出
+--
+--   B链:  bn/b1 → rov=uv/COUNT(1), ror=uv/COUNT(DISTINCT mid)
+--         b2    → rov=uv/b1_exp,    ror=uv/b1_uv
+--         b3    → rov=uv/b2_exp,    ror=uv/b2_uv
+--   C链全量: cn_1 → rov=uv/bn_exp,    ror=uv/bn_uv
+--            cn_2 → rov=uv/cn_1_exp,  ror=uv/cn_1_uv
+--            cn_3 → rov=uv/cn_2_exp,  ror=uv/cn_2_uv
+--   C链depth拆分: cX_Y → rov=uv/上级exp, ror=uv/上级uv (X=depth, Y=hop)
+--            hop1: c1_1→bn, c2_1→c1_1, c3_1→c2_1
+--            hop2: c1_2→cn_1, c2_2→c1_2, c3_2→c2_2
+--            hop3: c1_3→cn_2, c2_3→c1_3, c3_3→c2_3
+--   D链全量: dn_1 → rov=uv/d0,         ror=uv/COUNT(DISTINCT mid)
+--            dn_2 → rov=uv/dn_1_exp,   ror=uv/dn_1_uv
+--            dn_3 → rov=uv/dn_2_exp,   ror=uv/dn_2_uv
+--   D链depth拆分: dX_Y (同 C 链模式)
+--            hop1: d1_1→d0/mid, d2_1→d1_1, d3_1→d2_1
+--            hop2: d1_2→dn_1, d2_2→d1_2, d3_2→d2_2
+--            hop3: d1_3→dn_2, d2_3→d1_3, d3_3→d2_3
+--   全链路: all → rov=uv/COUNT(1), ror=uv/COUNT(DISTINCT mid)
+-- =====================================================================
+
+-- DROP TABLE IF EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209;
+-- CREATE TABLE IF NOT EXISTS loghubods.dwd_recsys_alg_exposure_agg_wide_20260209 (
+--     -- ==================== 维度列 ====================
+--     dt                         STRING    COMMENT '日期'
+--     ,user_type                  STRING    COMMENT '用户拉活量分层(R0&新用户/R1-50/R_180_330等,汇总为SUM)'
+--     ,hh_bucket                STRING    COMMENT '小时段(00-03/04-07/.../20-23,汇总为SUM)'
+--     ,head_merge_leve2         STRING    COMMENT '进入内容品类(headvideoid品类,汇总为SUM)'
+--     ,vid_merge_leve2          STRING    COMMENT '推荐内容品类(vid品类,TOP10曝光+其他,汇总为SUM)'
+--     ,vid_id                   STRING    COMMENT '内容id(品类曝光TOP1+其他,汇总为SUM)'
+
+--     -- ==================== 基础流量 ====================
+--     ,exposure_cnt             BIGINT    COMMENT '曝光次数'
+--     ,exposure_uv              BIGINT    COMMENT '曝光人数(mid去重)'
+--     ,vid_cnt                  BIGINT    COMMENT '视频个数(vid去重)'
+--     ,exposure_per_user        DOUBLE    COMMENT '人均曝光次数 = 曝光次数/曝光人数'
+
+--     -- ==================== 分享 & 回流漏斗 ====================
+--     ,share_exposure_cnt       BIGINT    COMMENT '产生分享的曝光数'
+--     ,share_cnt                BIGINT    COMMENT '分享总次数'
+--     ,return_exposure_cnt      BIGINT    COMMENT '产生回流的曝光数(含自身) = SUM(is_return_n)'
+--     ,return_exposure_cnt_noself BIGINT  COMMENT '产生回流的曝光数(非自身) = SUM(is_return_noself)'
+--     ,return_uv                BIGINT    COMMENT '回流人数(含自身) = SUM(return_n_uv)'
+--     ,return_uv_noself         BIGINT    COMMENT '回流人数(非自身) = SUM(return_n_uv_noself)'
+--     ,share_rate               DOUBLE    COMMENT '分享率 = share_exposure_cnt/exposure_cnt'
+--     ,return_rate              DOUBLE    COMMENT '回流率(含自身) = return_exposure_cnt/exposure_cnt'
+--     ,return_rate_noself       DOUBLE    COMMENT '回流率(非自身) = return_exposure_cnt_noself/exposure_cnt'
+--     ,share_return_rate        DOUBLE    COMMENT '分享→回流转化率(非自身) = return_exposure_cnt_noself/share_exposure_cnt'
+
+--     -- ==================== 模型预估: STR (曝光→非自身回流概率) ====================
+--     ,str_real                 DOUBLE    COMMENT '= return_rate_noself, 模型label'
+--     ,str_pred                 DOUBLE    COMMENT 'STR预估 = SUM(str_pred)/exposure_cnt'
+--     ,str_copc                 DOUBLE    COMMENT 'STR copc = str_real/str_pred'
+--     ,str_mae                  DOUBLE    COMMENT 'STR MAE = AVG(|str_pred - str_real|)'
+--     ,str_var                  DOUBLE    COMMENT 'STR VAR = VARIANCE(str_pred - str_real)'
+
+--     -- ==================== 模型预估: ROSN (条件回流UV, 非自身) ====================
+--     ,rosn_real                DOUBLE    COMMENT '= return_uv_noself/return_exposure_cnt_noself, 模型label'
+--     ,rosn_pred                DOUBLE    COMMENT 'ROSN预估 = SUM(rosn_pred WHERE is_return_noself=1)/SUM(is_return_noself)'
+--     ,rosn_copc                DOUBLE    COMMENT 'ROSN copc = rosn_real/rosn_pred'
+--     ,rosn_pred_origin         DOUBLE    COMMENT 'ROSN原始预估均值 = AVG(rosn_pred_origin)'
+--     ,rosn_mae                 DOUBLE    COMMENT 'ROSN MAE = AVG(|rosn_pred - rosn_real|) WHERE is_return_noself=1'
+--     ,rosn_var                 DOUBLE    COMMENT 'ROSN VAR = VARIANCE(rosn_pred - rosn_real) WHERE is_return_noself=1'
+
+--     -- ==================== 模型预估: ROVN (STR×ROSN) ====================
+--     ,rovn_real                DOUBLE    COMMENT '= return_uv_noself/exposure_cnt, 模型label'
+--     ,rovn_pred                DOUBLE    COMMENT 'rovn预估 = AVG(str_pred*rosn_pred)'
+--     ,rovn_copc                DOUBLE    COMMENT 'rovn copc = rovn_real/rovn_pred'
+--     ,rovn_mae                 DOUBLE    COMMENT 'rovn MAE = AVG(|rovn_pred - rovn_real|)'
+--     ,rovn_var                 DOUBLE    COMMENT 'rovn VAR = VARIANCE(rovn_pred - rovn_real)'
+--     ,sortscore_avg            DOUBLE    COMMENT 'sortscore均值'
+
+--     -- ==================== B链 (分享→点击) ====================
+--     ,bn_uv                    BIGINT    COMMENT 'B链全量: 回流去重人数'
+--     ,bn_pv                    BIGINT    COMMENT 'B链全量: 回流点击次数'
+--     ,bn_exp                   BIGINT    COMMENT 'B链全量: 回流session曝光数'
+--     ,bn_ror                   DOUBLE    COMMENT 'bn_uv/exposure_uv'
+--     ,bn_rov                   DOUBLE    COMMENT 'bn_uv/exposure_cnt'
+--     ,b1_uv                    BIGINT    COMMENT 'B链depth=1: 回流去重人数'
+--     ,b1_pv                    BIGINT    COMMENT 'B链depth=1: 回流点击次数'
+--     ,b1_exp                   BIGINT    COMMENT 'B链depth=1: 回流session曝光数'
+--     ,b1_ror                   DOUBLE    COMMENT 'b1_uv/exposure_uv'
+--     ,b1_rov                   DOUBLE    COMMENT 'b1_uv/exposure_cnt'
+--     ,b2_uv                    BIGINT    COMMENT 'B链depth=2: 回流去重人数'
+--     ,b2_pv                    BIGINT    COMMENT 'B链depth=2: 回流点击次数'
+--     ,b2_exp                   BIGINT    COMMENT 'B链depth=2: 回流session曝光数'
+--     ,b2_ror                   DOUBLE    COMMENT 'b2_uv/b1_uv'
+--     ,b2_rov                   DOUBLE    COMMENT 'b2_uv/b1_exp'
+--     ,b3_uv                    BIGINT    COMMENT 'B链depth=3: 回流去重人数'
+--     ,b3_pv                    BIGINT    COMMENT 'B链depth=3: 回流点击次数'
+--     ,b3_exp                   BIGINT    COMMENT 'B链depth=3: 回流session曝光数'
+--     ,b3_ror                   DOUBLE    COMMENT 'b3_uv/b2_uv'
+--     ,b3_rov                   DOUBLE    COMMENT 'b3_uv/b2_exp'
+
+--     -- ==================== C链 (全量depth, 按hop) ====================
+--     ,cn_1_uv                  BIGINT    COMMENT 'C链hop1: 回流去重人数'
+--     ,cn_1_pv                  BIGINT    COMMENT 'C链hop1: 回流点击次数'
+--     ,cn_1_exp                 BIGINT    COMMENT 'C链hop1: 回流session曝光数'
+--     ,cn_1_ror                 DOUBLE    COMMENT 'cn_1_uv/bn_uv'
+--     ,cn_1_rov                 DOUBLE    COMMENT 'cn_1_uv/bn_exp'
+--     ,cn_2_uv                  BIGINT    COMMENT 'C链hop2: 回流去重人数'
+--     ,cn_2_pv                  BIGINT    COMMENT 'C链hop2: 回流点击次数'
+--     ,cn_2_exp                 BIGINT    COMMENT 'C链hop2: 回流session曝光数'
+--     ,cn_2_ror                 DOUBLE    COMMENT 'cn_2_uv/cn_1_uv'
+--     ,cn_2_rov                 DOUBLE    COMMENT 'cn_2_uv/cn_1_exp'
+--     ,cn_3_uv                  BIGINT    COMMENT 'C链hop3: 回流去重人数'
+--     ,cn_3_pv                  BIGINT    COMMENT 'C链hop3: 回流点击次数'
+--     ,cn_3_exp                 BIGINT    COMMENT 'C链hop3: 回流session曝光数'
+--     ,cn_3_ror                 DOUBLE    COMMENT 'cn_3_uv/cn_2_uv'
+--     ,cn_3_rov                 DOUBLE    COMMENT 'cn_3_uv/cn_2_exp'
+--     ,cn_total_uv              BIGINT    COMMENT 'C链合计UV = cn_1_uv + cn_2_uv + cn_3_uv'
+--     ,cn_total_pv              BIGINT    COMMENT 'C链合计PV = cn_1_pv + cn_2_pv + cn_3_pv'
+--     ,cn_total_exp             BIGINT    COMMENT 'C链合计EXP = cn_1_exp + cn_2_exp + cn_3_exp'
+--     ,cn_total_ror             DOUBLE    COMMENT 'cn_total_uv/bn_uv'
+--     ,cn_total_rov             DOUBLE    COMMENT 'cn_total_uv/bn_exp'
+--     -- C链 depth拆分 hop1
+--     ,c1_1_uv                  BIGINT    COMMENT 'C链d1-hop1: 回流去重人数'
+--     ,c1_1_pv                  BIGINT    COMMENT 'C链d1-hop1: 回流点击次数'
+--     ,c1_1_exp                 BIGINT    COMMENT 'C链d1-hop1: 回流session曝光数'
+--     ,c1_1_ror                 DOUBLE    COMMENT 'c1_1_uv/bn_uv'
+--     ,c1_1_rov                 DOUBLE    COMMENT 'c1_1_uv/bn_exp'
+--     ,c2_1_uv                  BIGINT    COMMENT 'C链d2-hop1: 回流去重人数'
+--     ,c2_1_pv                  BIGINT    COMMENT 'C链d2-hop1: 回流点击次数'
+--     ,c2_1_exp                 BIGINT    COMMENT 'C链d2-hop1: 回流session曝光数'
+--     ,c2_1_ror                 DOUBLE    COMMENT 'c2_1_uv/c1_1_uv'
+--     ,c2_1_rov                 DOUBLE    COMMENT 'c2_1_uv/c1_1_exp'
+--     ,c3_1_uv                  BIGINT    COMMENT 'C链d3-hop1: 回流去重人数'
+--     ,c3_1_pv                  BIGINT    COMMENT 'C链d3-hop1: 回流点击次数'
+--     ,c3_1_exp                 BIGINT    COMMENT 'C链d3-hop1: 回流session曝光数'
+--     ,c3_1_ror                 DOUBLE    COMMENT 'c3_1_uv/c2_1_uv'
+--     ,c3_1_rov                 DOUBLE    COMMENT 'c3_1_uv/c2_1_exp'
+--     -- C链 depth拆分 hop2
+--     ,c1_2_uv                  BIGINT    COMMENT 'C链d1-hop2: 回流去重人数'
+--     ,c1_2_pv                  BIGINT    COMMENT 'C链d1-hop2: 回流点击次数'
+--     ,c1_2_exp                 BIGINT    COMMENT 'C链d1-hop2: 回流session曝光数'
+--     ,c1_2_ror                 DOUBLE    COMMENT 'c1_2_uv/cn_1_uv'
+--     ,c1_2_rov                 DOUBLE    COMMENT 'c1_2_uv/cn_1_exp'
+--     ,c2_2_uv                  BIGINT    COMMENT 'C链d2-hop2: 回流去重人数'
+--     ,c2_2_pv                  BIGINT    COMMENT 'C链d2-hop2: 回流点击次数'
+--     ,c2_2_exp                 BIGINT    COMMENT 'C链d2-hop2: 回流session曝光数'
+--     ,c2_2_ror                 DOUBLE    COMMENT 'c2_2_uv/c1_2_uv'
+--     ,c2_2_rov                 DOUBLE    COMMENT 'c2_2_uv/c1_2_exp'
+--     ,c3_2_uv                  BIGINT    COMMENT 'C链d3-hop2: 回流去重人数'
+--     ,c3_2_pv                  BIGINT    COMMENT 'C链d3-hop2: 回流点击次数'
+--     ,c3_2_exp                 BIGINT    COMMENT 'C链d3-hop2: 回流session曝光数'
+--     ,c3_2_ror                 DOUBLE    COMMENT 'c3_2_uv/c2_2_uv'
+--     ,c3_2_rov                 DOUBLE    COMMENT 'c3_2_uv/c2_2_exp'
+--     -- C链 depth拆分 hop3
+--     ,c1_3_uv                  BIGINT    COMMENT 'C链d1-hop3: 回流去重人数'
+--     ,c1_3_pv                  BIGINT    COMMENT 'C链d1-hop3: 回流点击次数'
+--     ,c1_3_exp                 BIGINT    COMMENT 'C链d1-hop3: 回流session曝光数'
+--     ,c1_3_ror                 DOUBLE    COMMENT 'c1_3_uv/cn_2_uv'
+--     ,c1_3_rov                 DOUBLE    COMMENT 'c1_3_uv/cn_2_exp'
+--     ,c2_3_uv                  BIGINT    COMMENT 'C链d2-hop3: 回流去重人数'
+--     ,c2_3_pv                  BIGINT    COMMENT 'C链d2-hop3: 回流点击次数'
+--     ,c2_3_exp                 BIGINT    COMMENT 'C链d2-hop3: 回流session曝光数'
+--     ,c2_3_ror                 DOUBLE    COMMENT 'c2_3_uv/c1_3_uv'
+--     ,c2_3_rov                 DOUBLE    COMMENT 'c2_3_uv/c1_3_exp'
+--     ,c3_3_uv                  BIGINT    COMMENT 'C链d3-hop3: 回流去重人数'
+--     ,c3_3_pv                  BIGINT    COMMENT 'C链d3-hop3: 回流点击次数'
+--     ,c3_3_exp                 BIGINT    COMMENT 'C链d3-hop3: 回流session曝光数'
+--     ,c3_3_ror                 DOUBLE    COMMENT 'c3_3_uv/c2_3_uv'
+--     ,c3_3_rov                 DOUBLE    COMMENT 'c3_3_uv/c2_3_exp'
+
+--     -- ==================== D链 (session内后续曝光传播) ====================
+--     ,d0                       BIGINT    COMMENT 'D链初始成本: session内后续曝光数'
+--     ,dn_1_uv                  BIGINT    COMMENT 'D链hop1: 回流去重人数'
+--     ,dn_1_pv                  BIGINT    COMMENT 'D链hop1: 回流点击次数'
+--     ,dn_1_exp                 BIGINT    COMMENT 'D链hop1: 回流session曝光数'
+--     ,dn_1_ror                 DOUBLE    COMMENT 'dn_1_uv/exposure_uv'
+--     ,dn_1_rov                 DOUBLE    COMMENT 'dn_1_uv/d0'
+--     ,dn_2_uv                  BIGINT    COMMENT 'D链hop2: 回流去重人数'
+--     ,dn_2_pv                  BIGINT    COMMENT 'D链hop2: 回流点击次数'
+--     ,dn_2_exp                 BIGINT    COMMENT 'D链hop2: 回流session曝光数'
+--     ,dn_2_ror                 DOUBLE    COMMENT 'dn_2_uv/dn_1_uv'
+--     ,dn_2_rov                 DOUBLE    COMMENT 'dn_2_uv/dn_1_exp'
+--     ,dn_3_uv                  BIGINT    COMMENT 'D链hop3: 回流去重人数'
+--     ,dn_3_pv                  BIGINT    COMMENT 'D链hop3: 回流点击次数'
+--     ,dn_3_exp                 BIGINT    COMMENT 'D链hop3: 回流session曝光数'
+--     ,dn_3_ror                 DOUBLE    COMMENT 'dn_3_uv/dn_2_uv'
+--     ,dn_3_rov                 DOUBLE    COMMENT 'dn_3_uv/dn_2_exp'
+--     ,dn_total_uv              BIGINT    COMMENT 'D链合计UV = dn_1_uv + dn_2_uv + dn_3_uv'
+--     ,dn_total_pv              BIGINT    COMMENT 'D链合计PV = dn_1_pv + dn_2_pv + dn_3_pv'
+--     ,dn_total_exp             BIGINT    COMMENT 'D链合计EXP = dn_1_exp + dn_2_exp + dn_3_exp'
+--     ,dn_total_ror             DOUBLE    COMMENT 'dn_total_uv/exposure_uv'
+--     ,dn_total_rov             DOUBLE    COMMENT 'dn_total_uv/d0'
+--     -- D链 depth拆分 hop1
+--     ,d1_1_uv                  BIGINT    COMMENT 'D链d1-hop1: 回流去重人数'
+--     ,d1_1_pv                  BIGINT    COMMENT 'D链d1-hop1: 回流点击次数'
+--     ,d1_1_exp                 BIGINT    COMMENT 'D链d1-hop1: 回流session曝光数'
+--     ,d1_1_ror                 DOUBLE    COMMENT 'd1_1_uv/exposure_uv'
+--     ,d1_1_rov                 DOUBLE    COMMENT 'd1_1_uv/d0'
+--     ,d2_1_uv                  BIGINT    COMMENT 'D链d2-hop1: 回流去重人数'
+--     ,d2_1_pv                  BIGINT    COMMENT 'D链d2-hop1: 回流点击次数'
+--     ,d2_1_exp                 BIGINT    COMMENT 'D链d2-hop1: 回流session曝光数'
+--     ,d2_1_ror                 DOUBLE    COMMENT 'd2_1_uv/d1_1_uv'
+--     ,d2_1_rov                 DOUBLE    COMMENT 'd2_1_uv/d1_1_exp'
+--     ,d3_1_uv                  BIGINT    COMMENT 'D链d3-hop1: 回流去重人数'
+--     ,d3_1_pv                  BIGINT    COMMENT 'D链d3-hop1: 回流点击次数'
+--     ,d3_1_exp                 BIGINT    COMMENT 'D链d3-hop1: 回流session曝光数'
+--     ,d3_1_ror                 DOUBLE    COMMENT 'd3_1_uv/d2_1_uv'
+--     ,d3_1_rov                 DOUBLE    COMMENT 'd3_1_uv/d2_1_exp'
+--     -- D链 depth拆分 hop2
+--     ,d1_2_uv                  BIGINT    COMMENT 'D链d1-hop2: 回流去重人数'
+--     ,d1_2_pv                  BIGINT    COMMENT 'D链d1-hop2: 回流点击次数'
+--     ,d1_2_exp                 BIGINT    COMMENT 'D链d1-hop2: 回流session曝光数'
+--     ,d1_2_ror                 DOUBLE    COMMENT 'd1_2_uv/dn_1_uv'
+--     ,d1_2_rov                 DOUBLE    COMMENT 'd1_2_uv/dn_1_exp'
+--     ,d2_2_uv                  BIGINT    COMMENT 'D链d2-hop2: 回流去重人数'
+--     ,d2_2_pv                  BIGINT    COMMENT 'D链d2-hop2: 回流点击次数'
+--     ,d2_2_exp                 BIGINT    COMMENT 'D链d2-hop2: 回流session曝光数'
+--     ,d2_2_ror                 DOUBLE    COMMENT 'd2_2_uv/d1_2_uv'
+--     ,d2_2_rov                 DOUBLE    COMMENT 'd2_2_uv/d1_2_exp'
+--     ,d3_2_uv                  BIGINT    COMMENT 'D链d3-hop2: 回流去重人数'
+--     ,d3_2_pv                  BIGINT    COMMENT 'D链d3-hop2: 回流点击次数'
+--     ,d3_2_exp                 BIGINT    COMMENT 'D链d3-hop2: 回流session曝光数'
+--     ,d3_2_ror                 DOUBLE    COMMENT 'd3_2_uv/d2_2_uv'
+--     ,d3_2_rov                 DOUBLE    COMMENT 'd3_2_uv/d2_2_exp'
+--     -- D链 depth拆分 hop3
+--     ,d1_3_uv                  BIGINT    COMMENT 'D链d1-hop3: 回流去重人数'
+--     ,d1_3_pv                  BIGINT    COMMENT 'D链d1-hop3: 回流点击次数'
+--     ,d1_3_exp                 BIGINT    COMMENT 'D链d1-hop3: 回流session曝光数'
+--     ,d1_3_ror                 DOUBLE    COMMENT 'd1_3_uv/dn_2_uv'
+--     ,d1_3_rov                 DOUBLE    COMMENT 'd1_3_uv/dn_2_exp'
+--     ,d2_3_uv                  BIGINT    COMMENT 'D链d2-hop3: 回流去重人数'
+--     ,d2_3_pv                  BIGINT    COMMENT 'D链d2-hop3: 回流点击次数'
+--     ,d2_3_exp                 BIGINT    COMMENT 'D链d2-hop3: 回流session曝光数'
+--     ,d2_3_ror                 DOUBLE    COMMENT 'd2_3_uv/d1_3_uv'
+--     ,d2_3_rov                 DOUBLE    COMMENT 'd2_3_uv/d1_3_exp'
+--     ,d3_3_uv                  BIGINT    COMMENT 'D链d3-hop3: 回流去重人数'
+--     ,d3_3_pv                  BIGINT    COMMENT 'D链d3-hop3: 回流点击次数'
+--     ,d3_3_exp                 BIGINT    COMMENT 'D链d3-hop3: 回流session曝光数'
+--     ,d3_3_ror                 DOUBLE    COMMENT 'd3_3_uv/d2_3_uv'
+--     ,d3_3_rov                 DOUBLE    COMMENT 'd3_3_uv/d2_3_exp'
+
+--     -- ==================== 全链路 ====================
+--     ,all_uv                   BIGINT    COMMENT '全链路拉回UV = bn_uv + cn_total_uv + dn_total_uv'
+--     ,all_pv                   BIGINT    COMMENT '全链路拉回PV = bn_pv + cn_total_pv + dn_total_pv'
+--     ,all_exp                  BIGINT    COMMENT '全链路拉回EXP = bn_exp + cn_total_exp + dn_total_exp'
+--     ,all_ror                  DOUBLE    COMMENT 'all_uv/exposure_uv'
+--     ,all_rov                  DOUBLE    COMMENT 'all_uv/exposure_cnt'
+-- )
+-- COMMENT '曝光回流链路CUBE聚合-宽表版 (5维度: 用户分层/小时段/进入品类TOP1/推荐品类TOP10/内容idTOP1)'
+-- ;
+
+
+-- -- =====================================================================
+-- -- INSERT: 从 wide 宽表聚合, CUBE 全维度组合
+-- -- =====================================================================
+
+-- -- SELECT * FROM loghubods.dwd_recsys_alg_exposure_agg_wide_20260209 WHERE dt = '${dt}' ORDER BY exposure_cnt DESC LIMIT 100;
+
+-- INSERT OVERWRITE TABLE loghubods.dwd_recsys_alg_exposure_agg_wide_20260209
+
+WITH
+-- 用户拉活量分层
+t_user_type AS (
+    SELECT  DISTINCT type, openid
+    FROM    loghubods.mid_share_return_people_1year
+    WHERE   dt = TO_CHAR(DATEADD(TO_DATE('${dt}','YYYYMMDD'),-1,'dd'),'YYYYMMDD')
+    AND     type IS NOT NULL
+    AND     type != 'S_ALL'
+    AND     type NOT REGEXP 'R50'
+)
+-- 模型预估分数
+,t_score AS (
+    SELECT  apptype
+            ,videoid
+            ,recommendtraceid
+            ,scoresmap
+            ,sortscore
+    FROM    (
+                SELECT  apptype
+                        ,videoid
+                        ,recommendtraceid
+                        ,scoresmap
+                        ,sortscore
+                        ,ROW_NUMBER() OVER (PARTITION BY apptype,videoid,recommendtraceid) AS rn
+                FROM    loghubods.statistics_log_hour
+                WHERE   dt LIKE '${dt}%'
+                AND     scoresmap IS NOT NULL
+            )
+    WHERE   rn = 1
+)
+-- TOP1 进入内容品类(场): 按回流人数取 TOP1
+,t_top_head_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.headvideoid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY SUM(CAST(is_return_noself AS BIGINT)) DESC
+    LIMIT   1
+)
+-- TOP10 推荐内容品类(货): 按曝光次数取 TOP10
+,t_top_vid_cate AS (
+    SELECT  vt.merge_leve2
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+    WHERE   base.dt = '${dt}'
+    AND     vt.merge_leve2 IS NOT NULL
+    GROUP BY vt.merge_leve2
+    ORDER BY COUNT(1) DESC
+    LIMIT   10
+)
+-- TOP1 内容id(货): 每品类按曝光次数取 TOP1 (曝光>10w)
+,t_top_vid AS (
+    SELECT  merge_leve2, vid
+    FROM    (
+                SELECT  vt.merge_leve2
+                        ,base.vid
+                        ,COUNT(1)                                                               AS exp_cnt
+                        ,ROW_NUMBER() OVER (PARTITION BY vt.merge_leve2 ORDER BY COUNT(1) DESC) AS rk
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+                JOIN    loghubods.video_merge_tag vt ON base.vid = vt.videoid
+                WHERE   base.dt = '${dt}'
+                AND     vt.merge_leve2 IS NOT NULL
+                GROUP BY vt.merge_leve2, base.vid
+                HAVING  exp_cnt > 100000
+            )
+    WHERE   rk <= 1
+)
+-- 宽表
+,t_wide AS (
+    SELECT  base.*
+            ,CASE WHEN e.type IS NULL OR e.type = 'R_0'                       THEN 'R0&新用户'
+                  WHEN e.type IN ('R_1','R_2_10','R_10_50')                    THEN 'R1-50'
+                  WHEN e.type IN ('R_50_100','R_100_180','R_180_330')           THEN 'R_180_330'
+                  ELSE e.type
+             END AS user_type
+            ,CASE WHEN th.merge_leve2 IS NOT NULL THEN vt_head.merge_leve2 ELSE '其他' END AS head_merge_leve2
+            ,CASE WHEN tv.merge_leve2 IS NOT NULL THEN vt_vid.merge_leve2  ELSE '其他' END AS vid_merge_leve2
+            ,CASE WHEN ti.vid IS NOT NULL          THEN base.vid           ELSE '其他' END AS vid_id
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.fmRov') AS DOUBLE) AS str_pred
+            ,1.22*POW(CAST(GET_JSON_OBJECT(e1.scoresmap,'$.NorXGBScore') AS DOUBLE),1.15) AS rosn_pred
+            ,CAST(GET_JSON_OBJECT(e1.scoresmap,'$.hasReturnRovScore') AS DOUBLE) AS rosn_pred_origin
+            ,e1.sortscore
+            ,CASE
+                WHEN CAST(hh AS INT) BETWEEN 0  AND 3  THEN '00-03'
+                WHEN CAST(hh AS INT) BETWEEN 4  AND 7  THEN '04-07'
+                WHEN CAST(hh AS INT) BETWEEN 8  AND 11 THEN '08-11'
+                WHEN CAST(hh AS INT) BETWEEN 12 AND 15 THEN '12-15'
+                WHEN CAST(hh AS INT) BETWEEN 16 AND 19 THEN '16-19'
+                WHEN CAST(hh AS INT) BETWEEN 20 AND 23 THEN '20-23'
+                ELSE '-'
+             END AS hh_bucket
+    FROM    loghubods.dwd_recsys_alg_exposure_base_20260209 base
+    LEFT JOIN t_user_type e
+    ON      SUBSTRING_INDEX(base.mid,'weixin_openid_',-1) = e.openid
+    LEFT JOIN loghubods.video_merge_tag vt_head
+    ON      base.headvideoid = vt_head.videoid
+    LEFT JOIN loghubods.video_merge_tag vt_vid
+    ON      base.vid = vt_vid.videoid
+    LEFT JOIN t_score e1
+    ON      base.apptype = e1.apptype
+    AND     base.vid = e1.videoid
+    AND     base.recomtraceid = e1.recommendtraceid
+    LEFT JOIN t_top_head_cate th
+    ON      vt_head.merge_leve2 = th.merge_leve2
+    LEFT JOIN t_top_vid_cate tv
+    ON      vt_vid.merge_leve2 = tv.merge_leve2
+    LEFT JOIN t_top_vid ti
+    ON      base.vid = ti.vid
+    WHERE   base.dt = '${dt}'
+)
+
+SELECT
+        -- ==================== 维度列 ====================
+        '${dt}'                                                                                     AS dt
+        ,CASE WHEN GROUPING(user_type) = 1 THEN 'SUM' ELSE NVL(user_type, 'SUM') END              AS user_type
+        ,CASE WHEN GROUPING(hh_bucket) = 1 THEN 'SUM' ELSE NVL(hh_bucket, 'SUM') END              AS hh_bucket
+        ,CASE WHEN GROUPING(head_merge_leve2) = 1 THEN 'SUM' ELSE NVL(head_merge_leve2, 'SUM') END AS head_merge_leve2
+        ,CASE WHEN GROUPING(vid_merge_leve2) = 1 THEN 'SUM' ELSE NVL(vid_merge_leve2, 'SUM') END   AS vid_merge_leve2
+        ,CASE WHEN GROUPING(vid_id) = 1 THEN 'SUM' ELSE NVL(vid_id, 'SUM') END                     AS vid_id
+
+        -- ==================== 基础流量 ====================
+        ,COUNT(1)                                                                       AS exposure_cnt
+        ,COUNT(DISTINCT mid)                                                            AS exposure_uv
+        ,COUNT(DISTINCT vid)                                                            AS vid_cnt
+        ,ROUND(COUNT(1) / COUNT(DISTINCT mid), 4)                                      AS exposure_per_user
+
+        -- ==================== 分享 & 回流漏斗 ====================
+        ,SUM(CAST(is_share AS BIGINT))                                                  AS share_exposure_cnt
+        ,SUM(CAST(share_cnt AS BIGINT))                                                 AS share_cnt
+        ,SUM(CAST(is_return_n AS BIGINT))                                               AS return_exposure_cnt
+        ,SUM(CAST(is_return_noself AS BIGINT))                                          AS return_exposure_cnt_noself
+        ,SUM(CAST(return_n_uv AS BIGINT))                                               AS return_uv
+        ,SUM(CAST(return_n_uv_noself AS BIGINT))                                        AS return_uv_noself
+        ,ROUND(COALESCE(SUM(CAST(is_share AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                            AS share_rate
+        ,ROUND(COALESCE(SUM(CAST(is_return_n AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                         AS return_rate
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                                    AS return_rate_noself
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(CAST(SUM(CAST(is_share AS BIGINT)) AS DOUBLE), 0), 0), 6)               AS share_return_rate
+
+        -- ==================== 模型预估: STR (曝光→非自身回流概率) ====================
+        ,ROUND(COALESCE(SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS str_real
+        ,ROUND(COALESCE(SUM(str_pred) / NULLIF(COUNT(1), 0), 0), 6)                          AS str_pred
+        ,ROUND(
+            (SUM(CAST(is_return_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(SUM(str_pred) / NULLIF(COUNT(1), 0), 0)
+        , 4)                                                                                   AS str_copc
+        ,ROUND(AVG(ABS(str_pred - CAST(is_return_noself AS BIGINT))), 6)                      AS str_mae
+        ,ROUND(VARIANCE(str_pred - CAST(is_return_noself AS BIGINT)), 6)                      AS str_var
+
+        -- ==================== 模型预估: ROSN (条件回流UV, 非自身) ====================
+        ,ROUND(COALESCE(
+            SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0)
+        , 0), 6)                                                                               AS rosn_real
+        ,ROUND(COALESCE(SUM(CASE WHEN CAST(is_return_noself AS BIGINT) = 1 THEN rosn_pred END) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0), 6)  AS rosn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0))
+            / NULLIF(SUM(CASE WHEN CAST(is_return_noself AS BIGINT) = 1 THEN rosn_pred END) / NULLIF(SUM(CAST(is_return_noself AS BIGINT)), 0), 0)
+        , 4)                                                                                   AS rosn_copc
+        ,ROUND(AVG(rosn_pred_origin), 6)                                                      AS rosn_pred_origin
+        ,ROUND(AVG(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN ABS(rosn_pred - CAST(return_n_uv_noself AS BIGINT))
+            END
+        ), 6)                                                                                  AS rosn_mae
+        ,ROUND(VARIANCE(
+            CASE WHEN CAST(is_return_noself AS BIGINT) = 1
+                 THEN rosn_pred - CAST(return_n_uv_noself AS BIGINT)
+            END
+        ), 6)                                                                                  AS rosn_var
+
+        -- ==================== 模型预估: ROVN (STR×ROSN) ====================
+        ,ROUND(COALESCE(SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0), 0), 6)  AS rovn_real
+        ,ROUND(AVG(str_pred * rosn_pred), 6)                                                    AS rovn_pred
+        ,ROUND(
+            (SUM(CAST(return_n_uv_noself AS BIGINT)) / NULLIF(COUNT(1), 0))
+            / NULLIF(AVG(str_pred * rosn_pred), 0)
+        , 4)                                                                                     AS rovn_copc
+        ,ROUND(AVG(ABS(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT))), 6)            AS rovn_mae
+        ,ROUND(VARIANCE(str_pred * rosn_pred - CAST(return_n_uv_noself AS BIGINT)), 6)        AS rovn_var
+        ,ROUND(AVG(CAST(sortscore AS DOUBLE)), 6)                                               AS sortscore_avg
+
+        -- ==================== B链 ====================
+        ,SUM(CAST(bn_uv AS BIGINT))                                                     AS bn_uv
+        ,SUM(CAST(bn_pv AS BIGINT))                                                     AS bn_pv
+        ,SUM(CAST(bn_exp AS BIGINT))                                                    AS bn_exp
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS bn_ror
+        ,ROUND(COALESCE(SUM(CAST(bn_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS bn_rov
+        ,SUM(CAST(b1_uv AS BIGINT))                                                     AS b1_uv
+        ,SUM(CAST(b1_pv AS BIGINT))                                                     AS b1_pv
+        ,SUM(CAST(b1_exp AS BIGINT))                                                    AS b1_exp
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)               AS b1_ror
+        ,ROUND(COALESCE(SUM(CAST(b1_uv AS BIGINT)) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0), 0), 6)                          AS b1_rov
+        ,SUM(CAST(b2_uv AS BIGINT))                                                     AS b2_uv
+        ,SUM(CAST(b2_pv AS BIGINT))                                                     AS b2_pv
+        ,SUM(CAST(b2_exp AS BIGINT))                                                    AS b2_exp
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b2_ror
+        ,ROUND(COALESCE(SUM(CAST(b2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b2_rov
+        ,SUM(CAST(b3_uv AS BIGINT))                                                     AS b3_uv
+        ,SUM(CAST(b3_pv AS BIGINT))                                                     AS b3_pv
+        ,SUM(CAST(b3_exp AS BIGINT))                                                    AS b3_exp
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS b3_ror
+        ,ROUND(COALESCE(SUM(CAST(b3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(b2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)       AS b3_rov
+
+        -- ==================== C链 (全量depth, 按hop) ====================
+        ,SUM(CAST(cn_1_uv AS BIGINT))                                                   AS cn_1_uv
+        ,SUM(CAST(cn_1_pv AS BIGINT))                                                   AS cn_1_pv
+        ,SUM(CAST(cn_1_exp AS BIGINT))                                                  AS cn_1_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS cn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS cn_1_rov
+        ,SUM(CAST(cn_2_uv AS BIGINT))                                                   AS cn_2_uv
+        ,SUM(CAST(cn_2_pv AS BIGINT))                                                   AS cn_2_pv
+        ,SUM(CAST(cn_2_exp AS BIGINT))                                                  AS cn_2_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_2_rov
+        ,SUM(CAST(cn_3_uv AS BIGINT))                                                   AS cn_3_uv
+        ,SUM(CAST(cn_3_pv AS BIGINT))                                                   AS cn_3_pv
+        ,SUM(CAST(cn_3_exp AS BIGINT))                                                  AS cn_3_exp
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS cn_3_ror
+        ,ROUND(COALESCE(SUM(CAST(cn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS cn_3_rov
+        ,SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))    AS cn_total_uv
+        ,SUM(CAST(cn_1_pv AS BIGINT)) + SUM(CAST(cn_2_pv AS BIGINT)) + SUM(CAST(cn_3_pv AS BIGINT))    AS cn_total_pv
+        ,SUM(CAST(cn_1_exp AS BIGINT)) + SUM(CAST(cn_2_exp AS BIGINT)) + SUM(CAST(cn_3_exp AS BIGINT))  AS cn_total_exp
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS cn_total_rov
+
+        -- ==================== C链 (按depth拆分) ====================
+        -- hop1
+        ,SUM(CAST(c1_1_uv AS BIGINT))                                                     AS c1_1_uv
+        ,SUM(CAST(c1_1_pv AS BIGINT))                                                     AS c1_1_pv
+        ,SUM(CAST(c1_1_exp AS BIGINT))                                                    AS c1_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)      AS c1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(bn_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)     AS c1_1_rov
+        ,SUM(CAST(c2_1_uv AS BIGINT))                                                     AS c2_1_uv
+        ,SUM(CAST(c2_1_pv AS BIGINT))                                                     AS c2_1_pv
+        ,SUM(CAST(c2_1_exp AS BIGINT))                                                    AS c2_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_1_rov
+        ,SUM(CAST(c3_1_uv AS BIGINT))                                                     AS c3_1_uv
+        ,SUM(CAST(c3_1_pv AS BIGINT))                                                     AS c3_1_pv
+        ,SUM(CAST(c3_1_exp AS BIGINT))                                                    AS c3_1_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_1_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_1_rov
+        -- hop2
+        ,SUM(CAST(c1_2_uv AS BIGINT))                                                     AS c1_2_uv
+        ,SUM(CAST(c1_2_pv AS BIGINT))                                                     AS c1_2_pv
+        ,SUM(CAST(c1_2_exp AS BIGINT))                                                    AS c1_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_2_rov
+        ,SUM(CAST(c2_2_uv AS BIGINT))                                                     AS c2_2_uv
+        ,SUM(CAST(c2_2_pv AS BIGINT))                                                     AS c2_2_pv
+        ,SUM(CAST(c2_2_exp AS BIGINT))                                                    AS c2_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_2_rov
+        ,SUM(CAST(c3_2_uv AS BIGINT))                                                     AS c3_2_uv
+        ,SUM(CAST(c3_2_pv AS BIGINT))                                                     AS c3_2_pv
+        ,SUM(CAST(c3_2_exp AS BIGINT))                                                    AS c3_2_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_2_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_2_rov
+        -- hop3
+        ,SUM(CAST(c1_3_uv AS BIGINT))                                                     AS c1_3_uv
+        ,SUM(CAST(c1_3_pv AS BIGINT))                                                     AS c1_3_pv
+        ,SUM(CAST(c1_3_exp AS BIGINT))                                                    AS c1_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(cn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c1_3_rov
+        ,SUM(CAST(c2_3_uv AS BIGINT))                                                     AS c2_3_uv
+        ,SUM(CAST(c2_3_pv AS BIGINT))                                                     AS c2_3_pv
+        ,SUM(CAST(c2_3_exp AS BIGINT))                                                    AS c2_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c2_3_rov
+        ,SUM(CAST(c3_3_uv AS BIGINT))                                                     AS c3_3_uv
+        ,SUM(CAST(c3_3_pv AS BIGINT))                                                     AS c3_3_pv
+        ,SUM(CAST(c3_3_exp AS BIGINT))                                                    AS c3_3_exp
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)    AS c3_3_ror
+        ,ROUND(COALESCE(SUM(CAST(c3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(c2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS c3_3_rov
+
+        -- ==================== D链 (全量depth, 按hop) ====================
+        ,SUM(CAST(d0 AS BIGINT))                                                        AS d0
+        ,SUM(CAST(dn_1_uv AS BIGINT))                                                   AS dn_1_uv
+        ,SUM(CAST(dn_1_pv AS BIGINT))                                                   AS dn_1_pv
+        ,SUM(CAST(dn_1_exp AS BIGINT))                                                  AS dn_1_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS dn_1_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS dn_1_rov
+        ,SUM(CAST(dn_2_uv AS BIGINT))                                                   AS dn_2_uv
+        ,SUM(CAST(dn_2_pv AS BIGINT))                                                   AS dn_2_pv
+        ,SUM(CAST(dn_2_exp AS BIGINT))                                                  AS dn_2_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_2_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_2_rov
+        ,SUM(CAST(dn_3_uv AS BIGINT))                                                   AS dn_3_uv
+        ,SUM(CAST(dn_3_pv AS BIGINT))                                                   AS dn_3_pv
+        ,SUM(CAST(dn_3_exp AS BIGINT))                                                  AS dn_3_exp
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS dn_3_ror
+        ,ROUND(COALESCE(SUM(CAST(dn_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS dn_3_rov
+        ,SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))    AS dn_total_uv
+        ,SUM(CAST(dn_1_pv AS BIGINT)) + SUM(CAST(dn_2_pv AS BIGINT)) + SUM(CAST(dn_3_pv AS BIGINT))    AS dn_total_pv
+        ,SUM(CAST(dn_1_exp AS BIGINT)) + SUM(CAST(dn_2_exp AS BIGINT)) + SUM(CAST(dn_3_exp AS BIGINT))  AS dn_total_exp
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_ror
+        ,ROUND(COALESCE(
+            (SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT)))
+            / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0)
+        , 0), 6)                                                                                                            AS dn_total_rov
+
+        -- ==================== D链 (按depth拆分) ====================
+        -- hop1
+        ,SUM(CAST(d1_1_uv AS BIGINT))                                                     AS d1_1_uv
+        ,SUM(CAST(d1_1_pv AS BIGINT))                                                     AS d1_1_pv
+        ,SUM(CAST(d1_1_exp AS BIGINT))                                                    AS d1_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0), 0), 6)            AS d1_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d0 AS BIGINT)) AS DOUBLE), 0), 0), 6)        AS d1_1_rov
+        ,SUM(CAST(d2_1_uv AS BIGINT))                                                     AS d2_1_uv
+        ,SUM(CAST(d2_1_pv AS BIGINT))                                                     AS d2_1_pv
+        ,SUM(CAST(d2_1_exp AS BIGINT))                                                    AS d2_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_1_rov
+        ,SUM(CAST(d3_1_uv AS BIGINT))                                                     AS d3_1_uv
+        ,SUM(CAST(d3_1_pv AS BIGINT))                                                     AS d3_1_pv
+        ,SUM(CAST(d3_1_exp AS BIGINT))                                                    AS d3_1_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_1_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_1_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_1_rov
+        -- hop2
+        ,SUM(CAST(d1_2_uv AS BIGINT))                                                     AS d1_2_uv
+        ,SUM(CAST(d1_2_pv AS BIGINT))                                                     AS d1_2_pv
+        ,SUM(CAST(d1_2_exp AS BIGINT))                                                    AS d1_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_1_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_2_rov
+        ,SUM(CAST(d2_2_uv AS BIGINT))                                                     AS d2_2_uv
+        ,SUM(CAST(d2_2_pv AS BIGINT))                                                     AS d2_2_pv
+        ,SUM(CAST(d2_2_exp AS BIGINT))                                                    AS d2_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_2_rov
+        ,SUM(CAST(d3_2_uv AS BIGINT))                                                     AS d3_2_uv
+        ,SUM(CAST(d3_2_pv AS BIGINT))                                                     AS d3_2_pv
+        ,SUM(CAST(d3_2_exp AS BIGINT))                                                    AS d3_2_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_2_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_2_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_2_rov
+        -- hop3
+        ,SUM(CAST(d1_3_uv AS BIGINT))                                                     AS d1_3_uv
+        ,SUM(CAST(d1_3_pv AS BIGINT))                                                     AS d1_3_pv
+        ,SUM(CAST(d1_3_exp AS BIGINT))                                                    AS d1_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d1_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d1_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(dn_2_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d1_3_rov
+        ,SUM(CAST(d2_3_uv AS BIGINT))                                                     AS d2_3_uv
+        ,SUM(CAST(d2_3_pv AS BIGINT))                                                     AS d2_3_pv
+        ,SUM(CAST(d2_3_exp AS BIGINT))                                                    AS d2_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d2_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d2_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d1_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d2_3_rov
+        ,SUM(CAST(d3_3_uv AS BIGINT))                                                     AS d3_3_uv
+        ,SUM(CAST(d3_3_pv AS BIGINT))                                                     AS d3_3_pv
+        ,SUM(CAST(d3_3_exp AS BIGINT))                                                    AS d3_3_exp
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_uv AS BIGINT)) AS DOUBLE), 0), 0), 6)   AS d3_3_ror
+        ,ROUND(COALESCE(SUM(CAST(d3_3_uv AS BIGINT)) / NULLIF(CAST(SUM(CAST(d2_3_exp AS BIGINT)) AS DOUBLE), 0), 0), 6)  AS d3_3_rov
+
+        -- ==================== 全链路 ====================
+        ,SUM(CAST(bn_uv AS BIGINT))
+            + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+            + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+                                                                                        AS all_uv
+        ,SUM(CAST(bn_pv AS BIGINT))
+            + SUM(CAST(cn_1_pv AS BIGINT)) + SUM(CAST(cn_2_pv AS BIGINT)) + SUM(CAST(cn_3_pv AS BIGINT))
+            + SUM(CAST(dn_1_pv AS BIGINT)) + SUM(CAST(dn_2_pv AS BIGINT)) + SUM(CAST(dn_3_pv AS BIGINT))
+                                                                                        AS all_pv
+        ,SUM(CAST(bn_exp AS BIGINT))
+            + SUM(CAST(cn_1_exp AS BIGINT)) + SUM(CAST(cn_2_exp AS BIGINT)) + SUM(CAST(cn_3_exp AS BIGINT))
+            + SUM(CAST(dn_1_exp AS BIGINT)) + SUM(CAST(dn_2_exp AS BIGINT)) + SUM(CAST(dn_3_exp AS BIGINT))
+                                                                                        AS all_exp
+        ,ROUND(COALESCE(
+            (   SUM(CAST(bn_uv AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(DISTINCT mid) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_ror
+        ,ROUND(COALESCE(
+            (   SUM(CAST(bn_uv AS BIGINT))
+              + SUM(CAST(cn_1_uv AS BIGINT)) + SUM(CAST(cn_2_uv AS BIGINT)) + SUM(CAST(cn_3_uv AS BIGINT))
+              + SUM(CAST(dn_1_uv AS BIGINT)) + SUM(CAST(dn_2_uv AS BIGINT)) + SUM(CAST(dn_3_uv AS BIGINT))
+            ) / NULLIF(CAST(COUNT(1) AS DOUBLE), 0)
+        , 0), 6)                                                                        AS all_rov
+
+
+-- =====================================================================
+-- FROM + GROUP BY CUBE
+-- =====================================================================
+
+FROM    t_wide
+
+GROUP BY CUBE(
+            user_type
+            ,hh_bucket
+            ,head_merge_leve2
+            ,vid_merge_leve2
+            ,vid_id
+        )
+
+ORDER BY exposure_cnt DESC
+;