yangxiaohui 1 deň pred
rodič
commit
bcb7c9d70e

+ 10 - 8
lib/odps_module.py

@@ -67,26 +67,28 @@ class ODPSClient(object):
         )
 
     def execute_sql(self, sql: str, print_logview: bool = True):
-        """执行 SQL 并返回 DataFrame"""
+        """执行 SQL 并返回 DataFrame(异步提交,LogView 秒出)"""
         hints = {'odps.sql.submit.mode': 'script'}
-        instance = self.odps.execute_sql(sql, hints=hints)
+        instance = self.odps.run_sql(sql, hints=hints)
 
         if print_logview:
             print(f"LogView: {instance.get_logview_address()}")
 
+        instance.wait_for_success()
         with instance.open_reader(tunnel=True, limit=False) as reader:
             pd_df = reader.to_pandas()
         return pd_df
 
     def execute_sql_result_save_file(self, sql: str, output_file: str):
-        """执行 SQL 并保存到文件(Arrow 直接写 CSV,速度最快)"""
+        """执行 SQL 并保存到文件(Arrow 直接写 CSV,速度最快;异步提交,LogView 秒出)"""
         hints = {'odps.sql.submit.mode': 'script'}
 
         start_time = time.time()
-        instance = self.odps.execute_sql(sql, hints=hints)
-        sql_time = time.time() - start_time
-
+        instance = self.odps.run_sql(sql, hints=hints)
         print(f"LogView: {instance.get_logview_address()}")
+
+        instance.wait_for_success()
+        sql_time = time.time() - start_time
         print(f"SQL 执行耗时: {sql_time:.1f}s")
 
         with instance.open_reader(tunnel=True, limit=False, arrow=True) as reader:
@@ -117,9 +119,9 @@ class ODPSClient(object):
 
         start_time = time.time()
 
-        # 1. 创建临时表
+        # 1. 创建临时表(异步提交,LogView 秒出)
         print(f"创建临时表: {tmp_table}")
-        instance = self.odps.execute_sql(create_sql, hints=hints)
+        instance = self.odps.run_sql(create_sql, hints=hints)
         print(f"LogView: {instance.get_logview_address()}")
         instance.wait_for_success()
         sql_time = time.time() - start_time

+ 152 - 0
tasks/00_DAU/dau_全维度.sql

@@ -0,0 +1,152 @@
+-- 分 apptype × 尾号 × 内外 × 来源大类 × 回流天数 × 微信场景 × AB 实验 DAU
+-- 基于 useractive_log 单表,无 JOIN
+--
+-- 7 个维度(含 dt),核心是 user_class 6 分类 + share_age_bucket 回流时长
+-- GROUPING SETS 精选了 8 组常用切片(不是全组合,避免行数爆炸)
+--
+-- 来源大类 user_class:
+--   A_外部投放拉来        : 本次被外部投放素材拉来(shareId 是 GUID 格式)
+--   B_用户分享_链根外部    : 被用户分享拉来 + 链根来自外部投放
+--   C_用户分享_链根内部    : 被用户分享拉来 + 链根是自然打开用户
+--   D_主动回流(外部血统)   : 本次主动启动 + 有外部回流残留
+--   E_主动回流(分享残留)   : 本次主动启动 + 仅有分享残留
+--   F_纯主动             : 真正凭记忆主动打开
+--
+-- 回流天数 share_age_bucket(仅对 B/C 有意义):
+--   d0  当天 / d1  1天前 / d2_7  2-7天前 / d8_30  8-30天前 / d30plus  >30天前
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,sessionid
+            ,subsessionid
+            ,clienttimestamp
+            ,sencetype
+            ,params
+            ,GET_JSON_OBJECT(extparams,'$.rootSessionId')           AS rsid
+            ,GET_JSON_OBJECT(extparams,'$.rootSourceId')            AS rscid
+            ,GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003')   AS ab003
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)  AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt = "${dt}"
+    AND     businesstype = 'path'
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') IS NOT NULL
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') <> ''
+),
+t_derived AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,COALESCE(ab003, 'unknown') AS ab003
+            ,SUBSTR(rsid, LENGTH(rsid), 1) AS suffix
+            -- 内/外二分(保留原口径,跟旧 SQL 对齐)
+            ,CASE
+                WHEN rscid IS NOT NULL AND rscid <> '' THEN '外部'
+                ELSE '内部'
+             END AS source_type
+            -- 微信场景大类(避免 cardinality 爆炸,归 6 类)
+            ,CASE sencetype
+                WHEN '1007'  THEN '1007_单聊'
+                WHEN '1008'  THEN '1008_群聊'
+                WHEN '1014'  THEN '1014_朋友圈'
+                WHEN '1044'  THEN '1044_群消息卡片'
+                WHEN '1154'  THEN '1154_视频号'
+                WHEN '1001'  THEN '1001_主入口'
+                ELSE 'other'
+             END AS scene_grp
+            -- 投放渠道前缀(rootSourceId 不为空时才有意义)
+            ,CASE
+                WHEN rscid LIKE 'touliu_tencent%'         THEN 'ch_touliu_tencent'
+                WHEN rscid LIKE 'dyyqw_%'                 THEN 'ch_dyyqw'
+                WHEN rscid LIKE 'dyyjs_%'                 THEN 'ch_dyyjs'
+                WHEN rscid LIKE '%GzhArticle%'
+                  OR rscid LIKE 'DaiTou_gh_%'             THEN 'ch_gzh_article'
+                WHEN rscid IS NULL OR rscid = ''          THEN 'ch_none'
+                ELSE 'ch_other'
+             END AS channel
+            -- 用户来源 6 分类
+            ,CASE
+                -- 本次被外部投放拉来(shareId GUID 格式)
+                WHEN params LIKE '%shareId=%'
+                 AND NOT (SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                          RLIKE '^[0-9]{13}$')
+                    THEN 'A_外部投放拉来'
+                -- 本次被用户分享拉来 + 链根外部
+                WHEN params LIKE '%shareId=%'
+                 AND (rscid IS NOT NULL AND rscid <> '')
+                    THEN 'B_用户分享_链根外部'
+                -- 本次被用户分享拉来 + 链根内部
+                WHEN params LIKE '%shareId=%'
+                    THEN 'C_用户分享_链根内部'
+                -- 主动启动 + 有外部回流残留
+                WHEN rscid IS NOT NULL AND rscid <> ''
+                    THEN 'D_主动回流_外部血统'
+                -- 主动启动 + 有分享残留
+                WHEN rsid <> sessionid AND rsid <> subsessionid
+                    THEN 'E_主动回流_分享残留'
+                ELSE 'F_纯主动'
+             END AS user_class
+            -- 回流天数(仅 shareId 有时间戳时计算)
+            ,CASE
+                WHEN params LIKE '%shareId=%'
+                 AND (SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                      RLIKE '^[0-9]{13}$')
+                THEN
+                    CAST((CAST(clienttimestamp AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                  - CAST((CAST(SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                              AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                ELSE NULL
+             END AS days_diff
+    FROM    t_base
+),
+t_final AS
+(
+    SELECT  dt, apptype, machinecode, ab003, suffix, source_type, scene_grp, channel, user_class
+            ,CASE
+                WHEN days_diff IS NULL                          THEN 'na'        -- 非分享回流
+                WHEN days_diff <= 0                             THEN 'd0_当天'
+                WHEN days_diff = 1                              THEN 'd1_1天前'
+                WHEN days_diff BETWEEN 2 AND 7                  THEN 'd2_7_一周内'
+                WHEN days_diff BETWEEN 8 AND 30                 THEN 'd8_30_一月内'
+                ELSE                                                 'd30plus_长尾'
+             END AS share_age_bucket
+    FROM t_derived
+)
+SELECT  dt
+        ,COALESCE(apptype,          'ALL') AS apptype
+        ,COALESCE(user_class,       'ALL') AS user_class
+        ,COALESCE(source_type,      'ALL') AS source_type
+        ,COALESCE(suffix,           'ALL') AS suffix
+        ,COALESCE(scene_grp,        'ALL') AS scene_grp
+        ,COALESCE(channel,          'ALL') AS channel
+        ,COALESCE(ab003,            'ALL') AS ab003
+        ,COALESCE(share_age_bucket, 'ALL') AS share_age_bucket
+        ,COUNT(DISTINCT machinecode)       AS dau
+FROM    t_final
+GROUP BY dt, apptype, user_class, source_type, suffix, scene_grp, channel, ab003, share_age_bucket
+GROUPING SETS (
+    -- ① 大盘日总量
+    (dt),
+    -- ② 大盘 × 来源(最常看)
+    (dt, user_class),
+    (dt, source_type),
+    -- ③ 大盘 × 来源 × 回流时长(衰减曲线)
+    (dt, user_class, share_age_bucket),
+    -- ④ 分 apptype 全量 + 分 apptype × 来源
+    (dt, apptype),
+    (dt, apptype, user_class),
+    (dt, apptype, source_type),
+    -- ⑤ 尾号实验维度(保留原 SQL 的核心切片)
+    (dt, apptype, suffix),
+    (dt, apptype, suffix, source_type),
+    -- ⑥ 尾号 × AB 实验(验证两套实验体系)
+    (dt, suffix, ab003),
+    -- ⑦ 微信场景拆分
+    (dt, scene_grp),
+    (dt, apptype, scene_grp, user_class),
+    -- ⑧ 投放渠道拆分
+    (dt, channel, user_class),
+    (dt, apptype, channel)
+)

+ 43 - 0
tasks/00_DAU/dau_分apptype.sql

@@ -0,0 +1,43 @@
+-- 分 apptype × 分尾号 × 内外 DAU,含汇总行
+-- 尾号定义:rootSessionId 最后一位 hex(与 00_尾号实验 保持一致)
+-- 内外定义:rootSourceId 非空 = 外部(从分享/外链进入),空 = 内部
+-- GROUPING SETS 一次产出明细 + 汇总:任一列为 'ALL' 表示该维度被聚合
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,SUBSTR(
+                GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),
+                1
+            ) AS suffix
+            ,CASE
+                WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL
+                 AND GET_JSON_OBJECT(extparams,'$.rootSourceId') <> ''
+                THEN '外部'
+                ELSE '内部'
+             END AS source_type
+    FROM    loghubods.useractive_log
+    WHERE   dt = "${dt}"
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') IS NOT NULL
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') <> ''
+)
+SELECT  dt
+        ,COALESCE(apptype,     'ALL') AS apptype
+        ,COALESCE(source_type, 'ALL') AS source_type
+        ,COALESCE(suffix,      'ALL') AS suffix
+        ,COUNT(DISTINCT machinecode)  AS dau
+FROM    t_base
+GROUP BY dt, apptype, suffix, source_type
+GROUPING SETS (
+    -- TODO: 选你要的汇总组合,注释掉不需要的行
+    (dt, apptype, suffix, source_type),   -- 明细:apptype × 尾号 × 内外
+    (dt, apptype, suffix),                -- 某 apptype × 尾号 合计(内外汇总)
+    (dt, apptype, source_type),           -- 某 apptype × 内外(尾号汇总)—— 看每个 app 的内外结构
+    (dt, apptype),                        -- 某 apptype 全量
+    (dt, source_type),                    -- 全 apptype × 内外(看大盘内外占比)
+    (dt)                                  -- 当日全量
+)
+ORDER BY dt, apptype, source_type, suffix
+;

+ 80 - 0
tasks/00_DAU/dau_分apptype_24h.sql

@@ -0,0 +1,80 @@
+-- 原 dau_分apptype.sql + share_age 维度 = 当天 / 24h内 / 24h外
+-- 定义(精确按时间差和自然日切,3 桶 disjoint):
+--   当天    = shareId 跟 dt 同一自然日(北京时间)
+--             OR 无 shareId 时间戳(主动/投放首层默认当天)
+--   24h内   = 跨日 AND (clientTs - shareTs) ≤ 24 小时
+--   24h外   = (clientTs - shareTs) > 24 小时
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,clienttimestamp
+            ,params
+            ,SUBSTR(
+                GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),
+                1
+            ) AS suffix
+            ,CASE
+                WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL
+                 AND GET_JSON_OBJECT(extparams,'$.rootSourceId') <> ''
+                THEN '外部'
+                ELSE '内部'
+             END AS source_type
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1) AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt = "${dt}"
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') IS NOT NULL
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') <> ''
+),
+t_parsed AS
+(
+    SELECT  dt, apptype, machinecode, suffix, source_type, clienttimestamp
+            ,share_id
+            ,SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2) AS sid_last
+            ,CASE WHEN params LIKE '%shareId=%' THEN 1 ELSE 0 END AS has_share
+    FROM    t_base
+),
+t_derived AS
+(
+    SELECT  dt, apptype, machinecode, suffix, source_type
+            ,CASE
+                -- 没有 shareId 或 shareId 末段不是 13 位时间戳 → 默认当天
+                WHEN has_share = 0 OR NOT (sid_last RLIKE '^[0-9]{13}$')
+                    THEN '1_当天'
+                -- 同一自然日(北京时间)
+                WHEN CAST((CAST(clienttimestamp AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                   = CAST((CAST(sid_last AS BIGINT)        + 28800000) / 86400000 AS BIGINT)
+                    THEN '1_当天'
+                -- 跨日 AND 时间差 ≤ 24 小时
+                WHEN (CAST(clienttimestamp AS BIGINT) - CAST(sid_last AS BIGINT)) <= 86400000
+                    THEN '2_24h内'
+                ELSE '3_24h外'
+             END AS share_age
+    FROM t_parsed
+)
+SELECT  dt
+        ,COALESCE(apptype,     'ALL') AS apptype
+        ,COALESCE(source_type, 'ALL') AS source_type
+        ,COALESCE(suffix,      'ALL') AS suffix
+        ,COALESCE(share_age,   'ALL') AS share_age
+        ,COUNT(DISTINCT machinecode)  AS dau
+FROM    t_derived
+GROUP BY dt, apptype, suffix, source_type, share_age
+GROUPING SETS (
+    (dt, apptype, suffix, source_type, share_age),
+    (dt, apptype, suffix, share_age),
+    (dt, apptype, source_type, share_age),
+    (dt, apptype, share_age),
+    (dt, source_type, share_age),
+    (dt, share_age),
+    -- 原 SQL 所有切片保留
+    (dt, apptype, suffix, source_type),
+    (dt, apptype, suffix),
+    (dt, apptype, source_type),
+    (dt, apptype),
+    (dt, source_type),
+    (dt)
+)
+ORDER BY dt, apptype, source_type, suffix, share_age

+ 71 - 0
tasks/00_DAU/dau_分apptype_24h2.sql

@@ -0,0 +1,71 @@
+-- 在原 dau_分apptype.sql 基础上加 share_age 维度 = 24h内 / 24h外(纯时间差,2 桶)
+-- 定义:
+--   24h内 = (clientTs - shareTs) ≤ 24 小时  OR 无可解析 shareId 时间戳(主动/投放首层)
+--   24h外 = (clientTs - shareTs) > 24 小时
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,clienttimestamp
+            ,params
+            ,SUBSTR(
+                GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),
+                1
+            ) AS suffix
+            ,CASE
+                WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL
+                 AND GET_JSON_OBJECT(extparams,'$.rootSourceId') <> ''
+                THEN '外部'
+                ELSE '内部'
+             END AS source_type
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1) AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt = "${dt}"
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') IS NOT NULL
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') <> ''
+),
+t_derived AS
+(
+    SELECT  dt, apptype, machinecode, suffix, source_type
+            ,CASE
+                -- ① 有可解析 shareId 时间戳 + 时间差 > 24h
+                WHEN params LIKE '%shareId=%'
+                 AND SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                       RLIKE '^[0-9]{13}$'
+                 AND (CAST(clienttimestamp AS BIGINT)
+                    - CAST(SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                           AS BIGINT)) > 86400000
+                    THEN '2_24h外'
+                -- ② 其他全部归 24h 内(≤24h 分享、主动、投放首层、shareId 异常)
+                ELSE '1_24h内'
+             END AS share_age
+    FROM t_base
+)
+SELECT  dt
+        ,COALESCE(apptype,     'ALL') AS apptype
+        ,COALESCE(source_type, 'ALL') AS source_type
+        ,COALESCE(suffix,      'ALL') AS suffix
+        ,COALESCE(share_age,   'ALL') AS share_age
+        ,COUNT(DISTINCT machinecode)  AS dau
+FROM    t_derived
+GROUP BY dt, apptype, suffix, source_type, share_age
+GROUPING SETS (
+    (dt, apptype, suffix, source_type, share_age),
+    (dt, apptype, suffix, share_age),
+    (dt, apptype, source_type, share_age),
+    (dt, apptype, share_age),
+    (dt, suffix, share_age),                       -- ← 补上次漏掉的"大盘 × 尾号 × share_age"
+    (dt, suffix, source_type, share_age),
+    (dt, source_type, share_age),
+    (dt, share_age),
+    -- 原 SQL 切片
+    (dt, apptype, suffix, source_type),
+    (dt, apptype, suffix),
+    (dt, apptype, source_type),
+    (dt, apptype),
+    (dt, source_type),
+    (dt)
+)
+ORDER BY dt, apptype, source_type, suffix, share_age

+ 68 - 0
tasks/00_DAU/dau_分apptype_当天.sql

@@ -0,0 +1,68 @@
+-- 在原 dau_分apptype.sql 基础上加一个维度:share_age = 当天 / 非当天
+-- 定义:
+--   "非当天" = 被以前日期产生的分享拉回(shareId 有时间戳 且 ts 日期 < dt)
+--   "当天"   = 所有其他情况(主动 / 投放首层 / 当天分享)—— 即"今天产生的流量"
+WITH t_base AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,clienttimestamp
+            ,params
+            ,SUBSTR(
+                GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),
+                1
+            ) AS suffix
+            ,CASE
+                WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL
+                 AND GET_JSON_OBJECT(extparams,'$.rootSourceId') <> ''
+                THEN '外部'
+                ELSE '内部'
+             END AS source_type
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1) AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt = "${dt}"
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') IS NOT NULL
+    AND     GET_JSON_OBJECT(extparams,'$.rootSessionId') <> ''
+),
+t_derived AS
+(
+    SELECT  dt, apptype, machinecode, suffix, source_type
+            ,CASE
+                -- 只有 shareId 末段是 13 位时间戳 且 日期 < dt 时才算"非当天"
+                WHEN params LIKE '%shareId=%'
+                 AND SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                       RLIKE '^[0-9]{13}$'
+                 AND CAST((CAST(clienttimestamp AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                   > CAST((CAST(SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                              AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                    THEN '非当天'
+                ELSE '当天'
+             END AS share_age
+    FROM t_base
+)
+SELECT  dt
+        ,COALESCE(apptype,     'ALL') AS apptype
+        ,COALESCE(source_type, 'ALL') AS source_type
+        ,COALESCE(suffix,      'ALL') AS suffix
+        ,COALESCE(share_age,   'ALL') AS share_age
+        ,COUNT(DISTINCT machinecode)  AS dau
+FROM    t_derived
+GROUP BY dt, apptype, suffix, source_type, share_age
+GROUPING SETS (
+    (dt, apptype, suffix, source_type, share_age),
+    (dt, apptype, suffix, share_age),
+    (dt, apptype, source_type, share_age),
+    (dt, apptype, share_age),
+    (dt, source_type, share_age),
+    (dt, share_age),
+    -- 保留原 SQL 的所有切片
+    (dt, apptype, suffix, source_type),
+    (dt, apptype, suffix),
+    (dt, apptype, source_type),
+    (dt, apptype),
+    (dt, source_type),
+    (dt)
+)
+ORDER BY dt, apptype, source_type, suffix, share_age

+ 34 - 13
tasks/00_尾号实验/base_all_new_v3_分层.sql

@@ -47,12 +47,15 @@ WITH t_suffix_group AS
     UNION ALL SELECT "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
     UNION ALL SELECT "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "20260514"
     UNION ALL SELECT "4", "ab", "实验组:供给来源加权实验", "20260515", "20260518"
-    UNION ALL SELECT "4", "ab", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "4", "ab", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT "4", "ab", "实验组:重排移除后处理实验", "20260527", "20260528"
+    UNION ALL SELECT "4", "ab", "实验组:重排移除后处理实验-单变量", "20260529", "29991231"
     UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
     UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260510"
     UNION ALL SELECT "4", "01", "对照组:变更str*ros建模目标实验", "20260511", "20260514"
-    UNION ALL SELECT "4", "01", "对照组:DNN模型-调参", "20260515", "29991231"
+    UNION ALL SELECT "4", "01", "对照组:DNN模型-调参", "20260515", "20260521"
+    UNION ALL SELECT "4", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
     UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
     UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "20260512"
@@ -61,23 +64,33 @@ WITH t_suffix_group AS
     UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
     UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
-    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "29991231"
+    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "20260521"
+    UNION ALL SELECT "4", "5d", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT "4", "5d", "实验组:召回改目标all_rov", "20260523", "29991231"
     UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
     UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
     UNION ALL SELECT "4", "34", "实验组:召回剔除低质召回实验", "20260508", "20260514"
     UNION ALL SELECT "4", "34", "实验组:DNN模型-调参", "20260515", "20260518"
-    UNION ALL SELECT "4", "34", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "4", "34", "实验组:一年行为个性化品类召回", "20260519", "20260528"
+    UNION ALL SELECT "4", "34", "实验组:召回过滤-preview缩短时间实", "20260529", "29991231"
     UNION ALL SELECT "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
     UNION ALL SELECT "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
     UNION ALL SELECT "4", "ef", "实验组:DNN模型",                 "20260407", "20260518"
-    UNION ALL SELECT "4", "ef", "实验组:DNN模型-调参",                 "20260519", "29991231"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型-调参",                 "20260519", "20260521"
+    UNION ALL SELECT "4", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT "4", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260523", "20260604"
+    UNION ALL SELECT "4", "ef", "实验组:uid风险用户判断剔除null实验", "20260605", "29991231"
     UNION ALL SELECT "4", "2c", "实验组:DNN模型-调参",            "20260413", "20260518"
-    UNION ALL SELECT "4", "2c", "实验组:一年行为个性化品类召回",            "20260519", "29991231"
+    UNION ALL SELECT "4", "2c", "实验组:一年行为个性化品类召回",            "20260519", "20260526"
+    UNION ALL SELECT "4", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "20260603"
+    UNION ALL SELECT "4", "2c", "实验组:召回侧统一粗排分截断实验", "20260604", "29991231"
     UNION ALL SELECT "4", "89", "对照组",                          "20260301", "20260510"
     UNION ALL SELECT "4", "89", "实验组:变更str*ros建模目标实验",                          "20260511", "20260514"
-    UNION ALL SELECT "4", "89", "实验组:DNN模型-调参",                          "20260515", "299991231"
-
+    UNION ALL SELECT "4", "89", "实验组:DNN模型-调参",                          "20260515", "20260520"
+    UNION ALL SELECT "4", "89", "实验组:省份热门rov召回-指标修正", "20260521", "20260522"
+    UNION ALL SELECT "4", "89", "实验组:召回加整体配额40%", "20260523", "20260604"
+    UNION ALL SELECT "4", "89", "实验组:召回粗排+扩配额80->120", "20260605", "29991231"
 
     -- ── apptype = 0 ──────────────────────────────────────────────────
     UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
@@ -89,7 +102,8 @@ WITH t_suffix_group AS
     UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
     UNION ALL SELECT "0", "01", "对照组:变更str*ros建模目标实验", "20260508", "20260513"
-    UNION ALL SELECT "0", "01", "对照组:DNN模型-调参", "20260514", "29991231"
+    UNION ALL SELECT "0", "01", "对照组:DNN模型-调参", "20260514", "20260521"
+    UNION ALL SELECT "0", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
     UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
     UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
@@ -108,13 +122,20 @@ WITH t_suffix_group AS
     UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
     UNION ALL SELECT "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
     UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
-    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "29991231"
-    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "29991231"
+    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "20260521"
+    UNION ALL SELECT "0", "5d", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "20260521"
+    UNION ALL SELECT "0", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260526"
+    UNION ALL SELECT "0", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "20260604"
+    UNION ALL SELECT "0", "ef", "实验组:uid风险用户判断剔除null实验", "20260605", "29991231"
     UNION ALL SELECT "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
     UNION ALL SELECT "0", "2c", "实验组:DNN模型-调参",                 "20260508", "20260518"
-    UNION ALL SELECT "0", "2c", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "0", "2c", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT "0", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
     UNION ALL SELECT "0", "89", "对照组",                          "20260301", "20260507"
-    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "29991231"
+    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "20260521"
+    UNION ALL SELECT "0", "89", "实验组:一年行为个性化品类召回", "20260522", "29991231"
 )
 ,t_base AS
 (

+ 10 - 0
tasks/00_尾号实验/base_all_new_v3_分层_24h.json

@@ -0,0 +1,10 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "dNnqCt",
+  "sort": "dt:desc,apptype:asc,suffix_group:asc,source_type:asc,layer_type:asc",
+  "order": {
+      "suffix_group": ["ab", "34", "2c", "67", "01", "5d", "ef", "89"]
+  },
+  "cols": null,
+  "append_cols": true
+}

+ 810 - 0
tasks/00_尾号实验/base_all_new_v3_分层_24h.sql

@@ -0,0 +1,810 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 两层尾号映射 (SCD Type 2 模式) — apptype = 0 + 4 合并版 + 基线对比 + 分层
+-- [硬编码版:基线 DAU2 预计算,无额外扫描]
+-- [v_24h: 在 dau2 基础上新增 dau_24h_in / dau_24h_out 两切片,及其 vs_5d / diff]
+-- 24h 切分定义(纯时间差,2 桶非 disjoint—一个 mid 可能两桶都有,跟 dau2 整体 GROUPING SETS 风格一致):
+--   24h内 = (clientTs - shareTs) ≤ 24h  OR shareId 无可解析时间戳(主动/投放首层默认归内)
+--   24h外 = (clientTs - shareTs) > 24h
+-- 分层维度:source_type(内部/外部) × layer_type(首层/裂变层),GROUPING SETS 同时产出总体
+--
+-- 第一层 t_suffix_group:物理尾号 → 分流桶 ID(16 个 hex 尾号分成 8 个 2-元桶)
+--   - 分流规则不变时,此层永不改
+--
+-- 第二层 t_experiment_map:分流桶 → 实验名 + 生效日期
+--   - 只列出"分配了具体实验"的桶,未列出的桶自动默认为"对照组"
+--   - 支持 1 对多:同一个实验占多个桶时,用同一 abcode 字符串多加几行
+--   - 实验切换:不删旧行,关闭 end_dt + 追加新行(保留历史可回溯)
+--
+-- ┌─ 基线配置 ──────────────────────────────────────────────────────────┐
+-- │  基线桶:89              (对照组物理桶,横向对比基准)              │
+-- │  基线天数:20260307~20260311(5 天均值,DAU2 纵向对比基准)         │
+-- │  apptype:0 + 4 合并输出,按 apptype 分别对比各自基线              │
+-- └─────────────────────────────────────────────────────────────────────┘
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/2:实验映射(按 apptype 分组) ─────────────────────────────┐
+-- │  新增 apptype 只需追加行,下游逻辑自动适配                           │
+-- │  未列出的桶 → 自动默认为"对照组"                                     │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    -- ── apptype = 4 ──────────────────────────────────────────────────
+    SELECT "4" AS apptype, "ab" AS suffix_group, "实验组:变更str*ros建模目标实验 有问题" AS abcode, "20260413" AS start_dt, "20260415" AS end_dt
+    UNION ALL SELECT "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260510"
+    UNION ALL SELECT "4", "01", "对照组:变更str*ros建模目标实验", "20260511", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "20260512"
+    UNION ALL SELECT "4", "67", "实验组:一年行为个性化品类召回", "20260513", "29991231"
+    UNION ALL SELECT "4", "5d", "实验组:解构特征排序str模型",     "20260314", "20260406"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "29991231"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "34", "实验组:召回剔除低质召回实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
+    UNION ALL SELECT "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型",                 "20260407", "29991231"
+    UNION ALL SELECT "4", "2c", "实验组:DNN模型-调参",            "20260413", "29991231"
+    UNION ALL SELECT "4", "89", "对照组",                          "20260301", "20260510"
+    UNION ALL SELECT "4", "89", "实验组:变更str*ros建模目标实验",                          "20260511", "299991231"
+
+
+    -- ── apptype = 0 ──────────────────────────────────────────────────
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验", "20260417", "20260429"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "0", "01", "对照组:变更str*ros建模目标实验", "20260508", "20260513"
+    UNION ALL SELECT "0", "01", "对照组:DNN模型-调参", "20260514", "29991231"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "34", "实验组:曝光建模v1+变更str*ros建模目标实验", "20260425", "20260425"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260426", "20260429"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260417", "20260513"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260514", "29991231"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "29991231"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型-调参",                 "20260508", "29991231"
+    UNION ALL SELECT "0", "89", "对照组",                          "20260301", "20260507"
+    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "29991231"
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") 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
+                        ,CASE WHEN a.rootsourceid = '' OR a.rootsourceid IS NULL THEN '内部' ELSE '外部' END AS source_type
+                        ,CASE WHEN GET_JSON_OBJECT(a.extend,'$.rootsessionid') = a.subsessionid THEN '首层' ELSE '裂变层' END AS layer_type
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                -- apptype=4: ab0-ab9; apptype=0: ab0-ab4,ab8,ab9(无 ab5/ab6/ab7)
+                AND     abcode NOT IN ("ab100")
+                AND     (apptype = "4"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab8","ab9"))
+                AND     (apptype = "0"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix, vid, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, abcode, suffix, vid, source_type, layer_type),
+        (dt, apptype, abcode, suffix, vid)
+    )
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+-- ECS = 2 * Σ(p_i * rank_i) - 1
+--   p_i    = vid 在桶内曝光占比
+--   rank_i = 按曝光降序的排名(1 起)
+-- 值域 [1, distinct_vid_cnt],越大越分散,越小越头部集中
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,source_type
+            ,layer_type
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,abcode
+                        ,suffix
+                        ,source_type
+                        ,layer_type
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, abcode, suffix, source_type, layer_type
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, abcode, suffix, source_type, layer_type
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, abcode, suffix, source_type, layer_type
+)
+-- 全平台每个 vid 的曝光度(作为 ARP 的 popularity reference)
+-- 注意:不过滤 abcode,让 reference 覆盖全部合法尾号
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, vid, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, vid, source_type, layer_type),
+        (dt, apptype, vid)
+    )
+)
+-- 桶内 ARP (Average Recommendation Popularity):推荐视频的平均热门度
+-- 按桶内曝光量加权:曝光越多的 vid 对 ARP 影响越大
+-- 组合 ECS + ARP 可识别四象限:
+--   高ECS + 低ARP = 分散 + 偏长尾        ✅ 理想
+--   高ECS + 高ARP = 分散 + 头部内部多样化  ⚠️ 需警惕
+--   低ECS + 低ARP = 集中 + 冷门(小众爆发) ❓ 特殊
+--   低ECS + 高ARP = 集中 + 头部            ❌ 模型坍缩
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.abcode
+            ,v.suffix
+            ,v.source_type
+            ,v.layer_type
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.source_type = g.source_type
+    AND     v.layer_type = g.layer_type
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.abcode, v.suffix, v.source_type, v.layer_type
+)
+-- dau2 + dau_24h_in / dau_24h_out:按单尾号聚合
+-- 24h 切分:(clientTs - shareTs) ≤ 86400000 ms 归 24h内(含无 shareId 时间戳的主动/投放首层)
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,COALESCE(sub.source_type,'总体') AS source_type
+            ,COALESCE(sub.layer_type,'总体') AS layer_type
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+            ,COUNT(DISTINCT CASE WHEN sub.share_age = '24h内' THEN sub.machinecode END) AS dau_24h_in
+            ,COUNT(DISTINCT CASE WHEN sub.share_age = '24h外' THEN sub.machinecode END) AS dau_24h_out
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),1) AS suffix
+                        ,CASE WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') != '' AND GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL THEN '外部' ELSE '内部' END AS source_type
+                        ,CASE WHEN GET_JSON_OBJECT(extparams,'$.rootSessionId') = subsessionid
+                                OR GET_JSON_OBJECT(extparams,'$.rootSessionId') = sessionid THEN '首层' ELSE '裂变层' END AS layer_type
+                        ,CASE
+                            WHEN params LIKE '%shareId=%'
+                             AND SUBSTR(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1),
+                                        LENGTH(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1))
+                                        - INSTR(REVERSE(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)),'-') + 2)
+                                   RLIKE '^[0-9]{13}$'
+                             AND (CAST(clienttimestamp AS BIGINT)
+                                - CAST(SUBSTR(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1),
+                                              LENGTH(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1))
+                                              - INSTR(REVERSE(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)),'-') + 2)
+                                              AS BIGINT)) > 86400000
+                                THEN '24h外'
+                            ELSE '24h内'
+                         END AS share_age
+                FROM    loghubods.useractive_log
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+             ,sub.source_type, sub.layer_type
+    GROUPING SETS (
+        (SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix, sub.source_type, sub.layer_type),
+        (SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix)
+    )
+)
+-- dau2 + dau_24h_in / dau_24h_out:按 suffix_group 求尾号均值
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,source_type
+            ,layer_type
+            ,AVG(dau2)        AS dau2
+            ,AVG(dau_24h_in)  AS dau_24h_in
+            ,AVG(dau_24h_out) AS dau_24h_out
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, abcode, suffix_group, source_type, layer_type
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            -- [NEW] 合并 ROV = bn_rov + cn_rov + dn_rov(三者分母同为 COUNT(1),可合并)
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            -- [NEW] 桶内去重 vid 数(ECS 的天然配套)
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix_group, suffix, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, abcode, suffix_group, suffix, source_type, layer_type),
+        (dt, apptype, abcode, suffix_group, suffix)
+    )
+)
+-- 按实验组求尾号均值(新增:合并 ROV + 分发多样性三件套)
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.abcode
+            ,b.suffix_group
+            ,b.source_type
+            ,b.layer_type
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            -- ECS 归一化比值:去掉池子大小的影响,纯形态指标
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            -- Gini 系数:快手/Twitter/Netflix 业界标准,数学上 Gini = 1 - ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    AND     b.source_type = e.source_type
+    AND     b.layer_type = e.layer_type
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    AND     b.source_type = a.source_type
+    AND     b.layer_type = a.layer_type
+    GROUP BY b.dt, b.apptype, b.abcode, b.suffix_group, b.source_type, b.layer_type
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 5 天均值 + 基线桶(89)横向对比
+-- ════════════════════════════════════════════════════════════════════════════
+-- ┌─ 配置区 2/2:基线 DAU2 + 24h_in/24h_out(按 apptype × suffix_group × 分层 预计算)─┐
+-- │  基线期 20260307~20260311,含分层(内部/外部 × 首层/裂变层)+ 总体          │
+-- │  3 列基线:dau2_base5, dau_24h_in_base5, dau_24h_out_base5                  │
+-- │  由 compute_base5_dau_24h.sql 单次扫描产出                                  │
+-- └────────────────────────────────────────────────────────────────────────────┘
+,t_dau2_base5 AS
+(
+    -- ── apptype = 0 ──
+    SELECT "0" AS apptype, "01" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15286.9 AS dau2_base5,   11742.5 AS dau_24h_in_base5,    5506.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5338.7 AS dau2_base5,    4167.5 AS dau_24h_in_base5,    1386.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  187129.6 AS dau2_base5,  153523.1 AS dau_24h_in_base5,   50205.7 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44733.8 AS dau2_base5,   44733.1 AS dau_24h_in_base5,       1.1 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  249670.1 AS dau2_base5,  211588.2 AS dau_24h_in_base5,   57031.6 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   16267.2 AS dau2_base5,   12572.1 AS dau_24h_in_base5,    5726.0 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5329.6 AS dau2_base5,    4174.2 AS dau_24h_in_base5,    1372.7 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  197412.2 AS dau2_base5,  161539.3 AS dau_24h_in_base5,   53451.6 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44619.2 AS dau2_base5,   44618.8 AS dau_24h_in_base5,       0.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  260724.7 AS dau2_base5,  220242.3 AS dau_24h_in_base5,   60484.4 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15772.9 AS dau2_base5,   12065.3 AS dau_24h_in_base5,    5688.7 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5333.4 AS dau2_base5,    4154.5 AS dau_24h_in_base5,    1399.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  194723.4 AS dau2_base5,  160492.7 AS dau_24h_in_base5,   51068.6 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44640.6 AS dau2_base5,   44640.2 AS dau_24h_in_base5,       1.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  257599.6 AS dau2_base5,  218730.9 AS dau_24h_in_base5,   58089.1 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15821.6 AS dau2_base5,   12133.7 AS dau_24h_in_base5,    5657.5 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5335.1 AS dau2_base5,    4133.8 AS dau_24h_in_base5,    1421.2 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  190093.3 AS dau2_base5,  155586.6 AS dau_24h_in_base5,   51561.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44822.5 AS dau2_base5,   44822.2 AS dau_24h_in_base5,       1.2 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  253203.9 AS dau2_base5,  214046.8 AS dau_24h_in_base5,   58573.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15751.5 AS dau2_base5,   12083.4 AS dau_24h_in_base5,    5685.5 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5313.1 AS dau2_base5,    4134.1 AS dau_24h_in_base5,    1388.6 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  195295.8 AS dau2_base5,  160712.4 AS dau_24h_in_base5,   51623.5 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44614.3 AS dau2_base5,   44613.9 AS dau_24h_in_base5,       1.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  258066.1 AS dau2_base5,  218879.2 AS dau_24h_in_base5,   58627.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15882.8 AS dau2_base5,   12176.0 AS dau_24h_in_base5,    5711.2 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5313.5 AS dau2_base5,    4130.5 AS dau_24h_in_base5,    1396.8 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  187742.4 AS dau2_base5,  153248.2 AS dau_24h_in_base5,   51456.2 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44555.1 AS dau2_base5,   44554.4 AS dau_24h_in_base5,       1.7 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  250653.7 AS dau2_base5,  211511.4 AS dau_24h_in_base5,   58496.2 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   16173.9 AS dau2_base5,   12435.2 AS dau_24h_in_base5,    5718.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5345.5 AS dau2_base5,    4169.1 AS dau_24h_in_base5,    1403.1 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  184413.5 AS dau2_base5,  150909.9 AS dau_24h_in_base5,   50004.3 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44612.0 AS dau2_base5,   44611.8 AS dau_24h_in_base5,       1.1 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  247714.1 AS dau2_base5,  209537.2 AS dau_24h_in_base5,   57055.0 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15491.7 AS dau2_base5,   11857.5 AS dau_24h_in_base5,    5626.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5350.4 AS dau2_base5,    4170.7 AS dau_24h_in_base5,    1402.9 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  184778.2 AS dau2_base5,  151087.4 AS dau_24h_in_base5,   50497.4 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44633.2 AS dau2_base5,   44633.0 AS dau_24h_in_base5,       1.1 AS dau_24h_out_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  247402.7 AS dau2_base5,  209129.6 AS dau_24h_in_base5,   57461.7 AS dau_24h_out_base5
+    -- ── apptype = 4 ──
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9358.8 AS dau2_base5,    7260.7 AS dau_24h_in_base5,    3200.9 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3953.4 AS dau2_base5,    3601.5 AS dau_24h_in_base5,     427.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  129526.8 AS dau2_base5,  105841.5 AS dau_24h_in_base5,   35792.7 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82839.8 AS dau2_base5,   82839.8 AS dau_24h_in_base5,       0.8 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  221923.1 AS dau2_base5,  195901.8 AS dau_24h_in_base5,   39397.2 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9556.8 AS dau2_base5,    7432.8 AS dau_24h_in_base5,    3261.9 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3935.1 AS dau2_base5,    3571.6 AS dau_24h_in_base5,     432.9 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  131426.8 AS dau2_base5,  107496.9 AS dau_24h_in_base5,   36272.3 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82767.1 AS dau2_base5,   82766.6 AS dau_24h_in_base5,       1.0 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  223926.3 AS dau2_base5,  197632.9 AS dau_24h_in_base5,   39941.5 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   11739.7 AS dau2_base5,    9593.2 AS dau_24h_in_base5,    3333.8 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3892.0 AS dau2_base5,    3534.0 AS dau_24h_in_base5,     425.0 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  126370.7 AS dau2_base5,  103033.3 AS dau_24h_in_base5,   35146.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82681.9 AS dau2_base5,   82681.3 AS dau_24h_in_base5,       1.6 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  220940.6 AS dau2_base5,  195221.6 AS dau_24h_in_base5,   38880.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9999.3 AS dau2_base5,    7834.9 AS dau_24h_in_base5,    3323.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3950.1 AS dau2_base5,    3589.5 AS dau_24h_in_base5,     427.7 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  128746.6 AS dau2_base5,  105217.7 AS dau_24h_in_base5,   35660.6 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82744.1 AS dau2_base5,   82743.8 AS dau_24h_in_base5,       0.9 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  221669.4 AS dau2_base5,  195737.5 AS dau_24h_in_base5,   39383.4 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9685.2 AS dau2_base5,    7559.5 AS dau_24h_in_base5,    3236.2 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3942.3 AS dau2_base5,    3570.0 AS dau_24h_in_base5,     443.6 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  125356.4 AS dau2_base5,  102055.0 AS dau_24h_in_base5,   34972.2 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82720.8 AS dau2_base5,   82720.6 AS dau_24h_in_base5,       0.8 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  217974.6 AS dau2_base5,  192298.3 AS dau_24h_in_base5,   38628.5 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   11370.5 AS dau2_base5,    9030.8 AS dau_24h_in_base5,    3594.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3964.6 AS dau2_base5,    3581.9 AS dau_24h_in_base5,     451.7 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  130128.5 AS dau2_base5,  106329.1 AS dau_24h_in_base5,   36053.3 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82614.5 AS dau2_base5,   82614.2 AS dau_24h_in_base5,       1.2 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  224279.4 AS dau2_base5,  197873.2 AS dau_24h_in_base5,   40074.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9481.3 AS dau2_base5,    7414.4 AS dau_24h_in_base5,    3193.5 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3933.9 AS dau2_base5,    3565.7 AS dau_24h_in_base5,     437.7 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  129952.9 AS dau2_base5,  106148.2 AS dau_24h_in_base5,   36087.3 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82784.3 AS dau2_base5,   82784.0 AS dau_24h_in_base5,       0.8 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  222393.9 AS dau2_base5,  196273.6 AS dau_24h_in_base5,   39693.4 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9533.7 AS dau2_base5,    7430.8 AS dau_24h_in_base5,    3211.2 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3947.6 AS dau2_base5,    3592.3 AS dau_24h_in_base5,     426.4 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  127244.0 AS dau2_base5,  103850.0 AS dau_24h_in_base5,   35449.1 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82754.4 AS dau2_base5,   82753.6 AS dau_24h_in_base5,       1.8 AS dau_24h_out_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  219735.4 AS dau2_base5,  193996.3 AS dau_24h_in_base5,   39061.3 AS dau_24h_out_base5
+)
+-- 合并主表 + dau2 / dau_24h_in / dau_24h_out + 三组 vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,b.dau_24h_in
+            ,b.dau_24h_out
+            ,ROUND(b.dau2        / NULLIF(c.dau2_base5,        0), 6) AS dau_vs_5d
+            ,ROUND(b.dau_24h_in  / NULLIF(c.dau_24h_in_base5,  0), 6) AS dau_24h_in_vs_5d
+            ,ROUND(b.dau_24h_out / NULLIF(c.dau_24h_out_base5, 0), 6) AS dau_24h_out_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    AND     a.source_type = b.source_type
+    AND     a.layer_type = b.layer_type
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_group = c.suffix_group
+    AND     a.source_type = c.source_type
+    AND     a.layer_type = c.layer_type
+)
+-- ┌─ 对照桶配置:每个 (apptype, 时间窗) 显式指定一个对照桶 ──────────────┐
+-- │  设计原则:硬编码、唯一、可读                                        │
+-- │  - 每行 (apptype, [start_dt,end_dt]) 必须不重叠,保证唯一命中        │
+-- │  - 切换对照桶时:闭旧行 end_dt + 加新行(SCD2 风格)                 │
+-- │  - 与 t_experiment_map 的"对照组"行**有意冗余**,作为 diff 基准的    │
+-- │    单一权威源,避免被实验注册改动间接影响                           │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    SELECT "4" AS apptype, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "20260510" AS end_dt
+    UNION ALL SELECT "4", "01", "20260511", "29991231"
+    UNION ALL SELECT "0", "89", "20260101", "20260507"
+    UNION ALL SELECT "0", "01", "20260508", "29991231"
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.source_type
+            ,c.layer_type
+            ,c.dau_vs_5d          AS ctrl_dau_vs_5d
+            ,c.dau_24h_in_vs_5d   AS ctrl_dau_24h_in_vs_5d
+            ,c.dau_24h_out_vs_5d  AS ctrl_dau_24h_out_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.abcode
+        ,r.suffix_group
+        ,r.source_type
+        ,r.layer_type
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        ,r.dau_24h_in
+        ,r.dau_24h_out
+        -- ── DAU2 纵向对比(vs 历史 5 天均值) ──
+        ,r.dau_vs_5d
+        ,r.dau_24h_in_vs_5d
+        ,r.dau_24h_out_vs_5d
+        -- ── 横向对比:当日各桶 vs 基线桶(89),公式 = 当前值 / 基线值 - 1 ──
+        ,ROUND(r.dau_vs_5d         / NULLIF(ctrl.ctrl_dau_vs_5d,         0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.dau_24h_in_vs_5d  / NULLIF(ctrl.ctrl_dau_24h_in_vs_5d,  0) - 1, 6) AS dau_24h_in_vs_5d_diff
+        ,ROUND(r.dau_24h_out_vs_5d / NULLIF(ctrl.ctrl_dau_24h_out_vs_5d, 0) - 1, 6) AS dau_24h_out_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        -- 复合指标:曝光量变化 × ROV变化 的联动效果
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+AND     r.source_type = ctrl.source_type
+AND     r.layer_type = ctrl.layer_type
+ORDER BY r.dt DESC, r.apptype, r.abcode, r.suffix_group, r.source_type, r.layer_type
+;

+ 10 - 0
tasks/00_尾号实验/base_all_new_v3_分层_当天.json

@@ -0,0 +1,10 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "AMUgLg",
+  "sort": "dt:desc,apptype:asc,suffix_group:asc,source_type:asc,layer_type:asc",
+  "order": {
+      "suffix_group": ["ab", "34", "2c", "67", "01", "5d", "ef", "89"]
+  },
+  "cols": null,
+  "append_cols": true
+}

+ 811 - 0
tasks/00_尾号实验/base_all_new_v3_分层_当天.sql

@@ -0,0 +1,811 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 两层尾号映射 (SCD Type 2 模式) — apptype = 0 + 4 合并版 + 基线对比 + 分层
+-- [硬编码版:基线 DAU2 预计算,无额外扫描]
+-- [v_当天: 在 dau2 基础上新增 dau_today / dau_non_today 两切片,及其 vs_5d / diff]
+-- 当天/非当天切分定义(按自然日,北京时间,2 桶非 disjoint):
+--   非当天 = shareId 有 13 位时间戳 且 ts 自然日 < dt 自然日
+--   当天   = 所有其他情况(同自然日 / 无时间戳 / shareId 异常)
+-- 分层维度:source_type(内部/外部) × layer_type(首层/裂变层),GROUPING SETS 同时产出总体
+--
+-- 第一层 t_suffix_group:物理尾号 → 分流桶 ID(16 个 hex 尾号分成 8 个 2-元桶)
+--   - 分流规则不变时,此层永不改
+--
+-- 第二层 t_experiment_map:分流桶 → 实验名 + 生效日期
+--   - 只列出"分配了具体实验"的桶,未列出的桶自动默认为"对照组"
+--   - 支持 1 对多:同一个实验占多个桶时,用同一 abcode 字符串多加几行
+--   - 实验切换:不删旧行,关闭 end_dt + 追加新行(保留历史可回溯)
+--
+-- ┌─ 基线配置 ──────────────────────────────────────────────────────────┐
+-- │  基线桶:89              (对照组物理桶,横向对比基准)              │
+-- │  基线天数:20260307~20260311(5 天均值,DAU2 纵向对比基准)         │
+-- │  apptype:0 + 4 合并输出,按 apptype 分别对比各自基线              │
+-- └─────────────────────────────────────────────────────────────────────┘
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/2:实验映射(按 apptype 分组) ─────────────────────────────┐
+-- │  新增 apptype 只需追加行,下游逻辑自动适配                           │
+-- │  未列出的桶 → 自动默认为"对照组"                                     │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    -- ── apptype = 4 ──────────────────────────────────────────────────
+    SELECT "4" AS apptype, "ab" AS suffix_group, "实验组:变更str*ros建模目标实验 有问题" AS abcode, "20260413" AS start_dt, "20260415" AS end_dt
+    UNION ALL SELECT "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260510"
+    UNION ALL SELECT "4", "01", "对照组:变更str*ros建模目标实验", "20260511", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "20260512"
+    UNION ALL SELECT "4", "67", "实验组:一年行为个性化品类召回", "20260513", "29991231"
+    UNION ALL SELECT "4", "5d", "实验组:解构特征排序str模型",     "20260314", "20260406"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "29991231"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "34", "实验组:召回剔除低质召回实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
+    UNION ALL SELECT "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型",                 "20260407", "29991231"
+    UNION ALL SELECT "4", "2c", "实验组:DNN模型-调参",            "20260413", "29991231"
+    UNION ALL SELECT "4", "89", "对照组",                          "20260301", "20260510"
+    UNION ALL SELECT "4", "89", "实验组:变更str*ros建模目标实验",                          "20260511", "299991231"
+
+
+    -- ── apptype = 0 ──────────────────────────────────────────────────
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验", "20260417", "20260429"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "0", "01", "对照组:变更str*ros建模目标实验", "20260508", "20260513"
+    UNION ALL SELECT "0", "01", "对照组:DNN模型-调参", "20260514", "29991231"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "34", "实验组:曝光建模v1+变更str*ros建模目标实验", "20260425", "20260425"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260426", "20260429"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260417", "20260513"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260514", "29991231"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "29991231"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型-调参",                 "20260508", "29991231"
+    UNION ALL SELECT "0", "89", "对照组",                          "20260301", "20260507"
+    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "29991231"
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") 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
+                        ,CASE WHEN a.rootsourceid = '' OR a.rootsourceid IS NULL THEN '内部' ELSE '外部' END AS source_type
+                        ,CASE WHEN GET_JSON_OBJECT(a.extend,'$.rootsessionid') = a.subsessionid THEN '首层' ELSE '裂变层' END AS layer_type
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                -- apptype=4: ab0-ab9; apptype=0: ab0-ab4,ab8,ab9(无 ab5/ab6/ab7)
+                AND     abcode NOT IN ("ab100")
+                AND     (apptype = "4"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab8","ab9"))
+                AND     (apptype = "0"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix, vid, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, abcode, suffix, vid, source_type, layer_type),
+        (dt, apptype, abcode, suffix, vid)
+    )
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+-- ECS = 2 * Σ(p_i * rank_i) - 1
+--   p_i    = vid 在桶内曝光占比
+--   rank_i = 按曝光降序的排名(1 起)
+-- 值域 [1, distinct_vid_cnt],越大越分散,越小越头部集中
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,source_type
+            ,layer_type
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,abcode
+                        ,suffix
+                        ,source_type
+                        ,layer_type
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, abcode, suffix, source_type, layer_type
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, abcode, suffix, source_type, layer_type
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, abcode, suffix, source_type, layer_type
+)
+-- 全平台每个 vid 的曝光度(作为 ARP 的 popularity reference)
+-- 注意:不过滤 abcode,让 reference 覆盖全部合法尾号
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, vid, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, vid, source_type, layer_type),
+        (dt, apptype, vid)
+    )
+)
+-- 桶内 ARP (Average Recommendation Popularity):推荐视频的平均热门度
+-- 按桶内曝光量加权:曝光越多的 vid 对 ARP 影响越大
+-- 组合 ECS + ARP 可识别四象限:
+--   高ECS + 低ARP = 分散 + 偏长尾        ✅ 理想
+--   高ECS + 高ARP = 分散 + 头部内部多样化  ⚠️ 需警惕
+--   低ECS + 低ARP = 集中 + 冷门(小众爆发) ❓ 特殊
+--   低ECS + 高ARP = 集中 + 头部            ❌ 模型坍缩
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.abcode
+            ,v.suffix
+            ,v.source_type
+            ,v.layer_type
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.source_type = g.source_type
+    AND     v.layer_type = g.layer_type
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.abcode, v.suffix, v.source_type, v.layer_type
+)
+-- dau2 + dau_today / dau_non_today:按单尾号聚合
+-- 当天/非当天切分:shareId 时间戳跟 dt 同一自然日(北京时间)→ 当天;跨日 → 非当天
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,COALESCE(sub.source_type,'总体') AS source_type
+            ,COALESCE(sub.layer_type,'总体') AS layer_type
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+            ,COUNT(DISTINCT CASE WHEN sub.share_age = '当天'   THEN sub.machinecode END) AS dau_today
+            ,COUNT(DISTINCT CASE WHEN sub.share_age = '非当天' THEN sub.machinecode END) AS dau_non_today
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')),1) AS suffix
+                        ,CASE WHEN GET_JSON_OBJECT(extparams,'$.rootSourceId') != '' AND GET_JSON_OBJECT(extparams,'$.rootSourceId') IS NOT NULL THEN '外部' ELSE '内部' END AS source_type
+                        ,CASE WHEN GET_JSON_OBJECT(extparams,'$.rootSessionId') = subsessionid
+                                OR GET_JSON_OBJECT(extparams,'$.rootSessionId') = sessionid THEN '首层' ELSE '裂变层' END AS layer_type
+                        ,CASE
+                            -- 有可解析 shareId 时间戳 且 自然日 < dt 自然日(北京时间)
+                            WHEN params LIKE '%shareId=%'
+                             AND SUBSTR(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1),
+                                        LENGTH(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1))
+                                        - INSTR(REVERSE(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)),'-') + 2)
+                                   RLIKE '^[0-9]{13}$'
+                             AND CAST((CAST(clienttimestamp AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                               > CAST((CAST(SUBSTR(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1),
+                                                   LENGTH(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1))
+                                                   - INSTR(REVERSE(SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)),'-') + 2)
+                                                   AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                                THEN '非当天'
+                            ELSE '当天'
+                         END AS share_age
+                FROM    loghubods.useractive_log
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+             ,sub.source_type, sub.layer_type
+    GROUPING SETS (
+        (SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix, sub.source_type, sub.layer_type),
+        (SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix)
+    )
+)
+-- dau2 + dau_today / dau_non_today:按 suffix_group 求尾号均值
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,source_type
+            ,layer_type
+            ,AVG(dau2)          AS dau2
+            ,AVG(dau_today)     AS dau_today
+            ,AVG(dau_non_today) AS dau_non_today
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, abcode, suffix_group, source_type, layer_type
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体') AS layer_type
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            -- [NEW] 合并 ROV = bn_rov + cn_rov + dn_rov(三者分母同为 COUNT(1),可合并)
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            -- [NEW] 桶内去重 vid 数(ECS 的天然配套)
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix_group, suffix, source_type, layer_type
+    GROUPING SETS (
+        (dt, apptype, abcode, suffix_group, suffix, source_type, layer_type),
+        (dt, apptype, abcode, suffix_group, suffix)
+    )
+)
+-- 按实验组求尾号均值(新增:合并 ROV + 分发多样性三件套)
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.abcode
+            ,b.suffix_group
+            ,b.source_type
+            ,b.layer_type
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            -- ECS 归一化比值:去掉池子大小的影响,纯形态指标
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            -- Gini 系数:快手/Twitter/Netflix 业界标准,数学上 Gini = 1 - ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    AND     b.source_type = e.source_type
+    AND     b.layer_type = e.layer_type
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    AND     b.source_type = a.source_type
+    AND     b.layer_type = a.layer_type
+    GROUP BY b.dt, b.apptype, b.abcode, b.suffix_group, b.source_type, b.layer_type
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 5 天均值 + 基线桶(89)横向对比
+-- ════════════════════════════════════════════════════════════════════════════
+-- ┌─ 配置区 2/2:基线 DAU2 + 当天/非当天(按 apptype × suffix_group × 分层 预计算)  ┐
+-- │  基线期 20260307~20260311,含分层(内部/外部 × 首层/裂变层)+ 总体          │
+-- │  3 列基线:dau2_base5, dau_today_base5, dau_non_today_base5                │
+-- │  由 compute_base5_dau_today.sql 单次扫描产出                                │
+-- └────────────────────────────────────────────────────────────────────────────┘
+,t_dau2_base5 AS
+(
+    -- ── apptype = 0 ──
+    SELECT "0" AS apptype, "01" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15286.9 AS dau2_base5,   10450.8 AS dau_today_base5,    7366.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5338.7 AS dau2_base5,    4161.5 AS dau_today_base5,    1394.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  187129.6 AS dau2_base5,  131797.6 AS dau_today_base5,   80785.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44733.8 AS dau2_base5,   44731.4 AS dau_today_base5,       7.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "01" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  249670.1 AS dau2_base5,  188647.3 AS dau_today_base5,   89464.5 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   16267.2 AS dau2_base5,   11099.8 AS dau_today_base5,    7848.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5329.6 AS dau2_base5,    4168.9 AS dau_today_base5,    1379.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  197412.2 AS dau2_base5,  137089.1 AS dau_today_base5,   87436.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44619.2 AS dau2_base5,   44617.2 AS dau_today_base5,       7.3 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "2c" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  260724.7 AS dau2_base5,  194408.3 AS dau_today_base5,   96579.4 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15772.9 AS dau2_base5,   10671.8 AS dau_today_base5,    7673.9 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5333.4 AS dau2_base5,    4148.1 AS dau_today_base5,    1408.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  194723.4 AS dau2_base5,  136472.7 AS dau_today_base5,   84689.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44640.6 AS dau2_base5,   44638.8 AS dau_today_base5,       6.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "34" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  257599.6 AS dau2_base5,  193399.5 AS dau_today_base5,   93686.7 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15821.6 AS dau2_base5,   10706.2 AS dau_today_base5,    7684.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5335.1 AS dau2_base5,    4128.1 AS dau_today_base5,    1428.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  190093.3 AS dau2_base5,  133443.5 AS dau_today_base5,   82811.7 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44822.5 AS dau2_base5,   44820.8 AS dau_today_base5,       6.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "5d" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  253203.9 AS dau2_base5,  190557.9 AS dau_today_base5,   91840.5 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15751.5 AS dau2_base5,   10740.7 AS dau_today_base5,    7629.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5313.1 AS dau2_base5,    4128.0 AS dau_today_base5,    1396.3 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  195295.8 AS dau2_base5,  137592.3 AS dau_today_base5,   84025.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44614.3 AS dau2_base5,   44612.5 AS dau_today_base5,       7.2 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "67" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  258066.1 AS dau2_base5,  194500.7 AS dau_today_base5,   92964.3 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15882.8 AS dau2_base5,   10742.3 AS dau_today_base5,    7745.0 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5313.5 AS dau2_base5,    4123.5 AS dau_today_base5,    1405.6 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  187742.4 AS dau2_base5,  131173.5 AS dau_today_base5,   82476.3 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44555.1 AS dau2_base5,   44552.9 AS dau_today_base5,       7.9 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "89" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  250653.7 AS dau2_base5,  188086.4 AS dau_today_base5,   91543.4 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   16173.9 AS dau2_base5,   10932.8 AS dau_today_base5,    7859.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5345.5 AS dau2_base5,    4162.9 AS dau_today_base5,    1411.0 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  184413.5 AS dau2_base5,  128549.5 AS dau_today_base5,   81333.0 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44612.0 AS dau2_base5,   44609.6 AS dau_today_base5,       7.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ab" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  247714.1 AS dau2_base5,  185757.5 AS dau_today_base5,   90515.0 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   15491.7 AS dau2_base5,   10490.3 AS dau_today_base5,    7589.8 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    5350.4 AS dau2_base5,    4165.7 AS dau_today_base5,    1408.6 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  184778.2 AS dau2_base5,  129116.8 AS dau_today_base5,   81254.1 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   44633.2 AS dau2_base5,   44631.8 AS dau_today_base5,       6.4 AS dau_non_today_base5
+    UNION ALL SELECT "0" AS apptype, "ef" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  247402.7 AS dau2_base5,  185877.8 AS dau_today_base5,   90170.1 AS dau_non_today_base5
+    -- ── apptype = 4 ──
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9358.8 AS dau2_base5,    6416.4 AS dau_today_base5,    4418.5 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3953.4 AS dau2_base5,    3564.4 AS dau_today_base5,     469.8 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  129526.8 AS dau2_base5,   91714.0 AS dau_today_base5,   55696.3 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82839.8 AS dau2_base5,   82835.6 AS dau_today_base5,      15.8 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "01" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  221923.1 AS dau2_base5,  180942.0 AS dau_today_base5,   60564.2 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9556.8 AS dau2_base5,    6596.1 AS dau_today_base5,    4458.0 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3935.1 AS dau2_base5,    3533.1 AS dau_today_base5,     476.6 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  131426.8 AS dau2_base5,   93345.9 AS dau_today_base5,   56275.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82767.1 AS dau2_base5,   82763.9 AS dau_today_base5,      11.3 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "2c" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  223926.3 AS dau2_base5,  182652.4 AS dau_today_base5,   61185.7 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   11739.7 AS dau2_base5,    8527.1 AS dau_today_base5,    4931.0 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3892.0 AS dau2_base5,    3493.5 AS dau_today_base5,     470.8 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  126370.7 AS dau2_base5,   89177.1 AS dau_today_base5,   54556.0 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82681.9 AS dau2_base5,   82678.6 AS dau_today_base5,      12.2 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "34" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  220940.6 AS dau2_base5,  180308.9 AS dau_today_base5,   59932.8 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9999.3 AS dau2_base5,    6947.3 AS dau_today_base5,    4599.6 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3950.1 AS dau2_base5,    3551.3 AS dau_today_base5,     471.5 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  128746.6 AS dau2_base5,   91222.1 AS dau_today_base5,   55344.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82744.1 AS dau2_base5,   82740.2 AS dau_today_base5,      13.4 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "5d" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  221669.4 AS dau2_base5,  180865.7 AS dau_today_base5,   60388.7 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9685.2 AS dau2_base5,    6668.9 AS dau_today_base5,    4498.7 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3942.3 AS dau2_base5,    3534.9 AS dau_today_base5,     483.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  125356.4 AS dau2_base5,   88303.1 AS dau_today_base5,   54262.7 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82720.8 AS dau2_base5,   82716.3 AS dau_today_base5,      13.3 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "67" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  217974.6 AS dau2_base5,  177669.0 AS dau_today_base5,   59224.0 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,   11370.5 AS dau2_base5,    7867.4 AS dau_today_base5,    5296.2 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3964.6 AS dau2_base5,    3543.9 AS dau_today_base5,     494.2 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  130128.5 AS dau2_base5,   92237.2 AS dau_today_base5,   55873.9 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82614.5 AS dau2_base5,   82610.8 AS dau_today_base5,      13.4 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "89" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  224279.4 AS dau2_base5,  182631.2 AS dau_today_base5,   61641.2 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9481.3 AS dau2_base5,    6584.5 AS dau_today_base5,    4386.6 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3933.9 AS dau2_base5,    3525.7 AS dau_today_base5,     484.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  129952.9 AS dau2_base5,   92020.2 AS dau_today_base5,   55989.9 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82784.3 AS dau2_base5,   82782.4 AS dau_today_base5,      10.6 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ab" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  222393.9 AS dau2_base5,  181324.7 AS dau_today_base5,   60836.9 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "裂变层" AS layer_type,    9533.7 AS dau2_base5,    6606.6 AS dau_today_base5,    4389.3 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "内部" AS source_type, "首层" AS layer_type,    3947.6 AS dau2_base5,    3552.3 AS dau_today_base5,     472.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "裂变层" AS layer_type,  127244.0 AS dau2_base5,   89887.7 AS dau_today_base5,   55068.7 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "外部" AS source_type, "首层" AS layer_type,   82754.4 AS dau2_base5,   82749.9 AS dau_today_base5,      13.1 AS dau_non_today_base5
+    UNION ALL SELECT "4" AS apptype, "ef" AS suffix_group, "总体" AS source_type, "总体" AS layer_type,  219735.4 AS dau2_base5,  179218.3 AS dau_today_base5,   59907.0 AS dau_non_today_base5
+)
+-- 合并主表 + dau2 / dau_today / dau_non_today + 三组 vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,b.dau_today
+            ,b.dau_non_today
+            ,ROUND(b.dau2          / NULLIF(c.dau2_base5,          0), 6) AS dau_vs_5d
+            ,ROUND(b.dau_today     / NULLIF(c.dau_today_base5,     0), 6) AS dau_today_vs_5d
+            ,ROUND(b.dau_non_today / NULLIF(c.dau_non_today_base5, 0), 6) AS dau_non_today_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    AND     a.source_type = b.source_type
+    AND     a.layer_type = b.layer_type
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_group = c.suffix_group
+    AND     a.source_type = c.source_type
+    AND     a.layer_type = c.layer_type
+)
+-- ┌─ 对照桶配置:每个 (apptype, 时间窗) 显式指定一个对照桶 ──────────────┐
+-- │  设计原则:硬编码、唯一、可读                                        │
+-- │  - 每行 (apptype, [start_dt,end_dt]) 必须不重叠,保证唯一命中        │
+-- │  - 切换对照桶时:闭旧行 end_dt + 加新行(SCD2 风格)                 │
+-- │  - 与 t_experiment_map 的"对照组"行**有意冗余**,作为 diff 基准的    │
+-- │    单一权威源,避免被实验注册改动间接影响                           │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    SELECT "4" AS apptype, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "20260510" AS end_dt
+    UNION ALL SELECT "4", "01", "20260511", "29991231"
+    UNION ALL SELECT "0", "89", "20260101", "20260507"
+    UNION ALL SELECT "0", "01", "20260508", "29991231"
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.source_type
+            ,c.layer_type
+            ,c.dau_vs_5d            AS ctrl_dau_vs_5d
+            ,c.dau_today_vs_5d      AS ctrl_dau_today_vs_5d
+            ,c.dau_non_today_vs_5d  AS ctrl_dau_non_today_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.abcode
+        ,r.suffix_group
+        ,r.source_type
+        ,r.layer_type
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        ,r.dau_today
+        ,r.dau_non_today
+        -- ── DAU2 纵向对比(vs 历史 5 天均值) ──
+        ,r.dau_vs_5d
+        ,r.dau_today_vs_5d
+        ,r.dau_non_today_vs_5d
+        -- ── 横向对比:当日各桶 vs 基线桶(89),公式 = 当前值 / 基线值 - 1 ──
+        ,ROUND(r.dau_vs_5d           / NULLIF(ctrl.ctrl_dau_vs_5d,           0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.dau_today_vs_5d     / NULLIF(ctrl.ctrl_dau_today_vs_5d,     0) - 1, 6) AS dau_today_vs_5d_diff
+        ,ROUND(r.dau_non_today_vs_5d / NULLIF(ctrl.ctrl_dau_non_today_vs_5d, 0) - 1, 6) AS dau_non_today_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        -- 复合指标:曝光量变化 × ROV变化 的联动效果
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+AND     r.source_type = ctrl.source_type
+AND     r.layer_type = ctrl.layer_type
+ORDER BY r.dt DESC, r.apptype, r.abcode, r.suffix_group, r.source_type, r.layer_type
+;

+ 699 - 0
tasks/00_尾号实验/base_all_new_v3_汇总.sql

@@ -0,0 +1,699 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 两层尾号映射 (SCD Type 2 模式) — apptype = 0 + 4 合并版 + 基线对比
+-- [汇总版:不分 source_type / layer_type;DAU2 基线由 SQL 计算可配置]
+--
+-- 第一层 t_suffix_group:物理尾号 → 分流桶 ID(16 个 hex 尾号分成 8 个 2-元桶)
+--   - 分流规则不变时,此层永不改
+--
+-- 第二层 t_experiment_map:分流桶 → 实验名 + 生效日期
+--   - 只列出"分配了具体实验"的桶,未列出的桶自动默认为"对照组"
+--   - 支持 1 对多:同一个实验占多个桶时,用同一 abcode 字符串多加几行
+--   - 实验切换:不删旧行,关闭 end_dt + 追加新行(保留历史可回溯)
+--
+-- ┌─ 基线配置 ──────────────────────────────────────────────────────────┐
+-- │  对照桶:见 t_ctrl_bucket(横向对比基准,可按时间窗切换)             │
+-- │  基线天数:见 t_base5_window(DAU2 纵向对比基准,SQL 计算可配置)    │
+-- │  apptype:0 + 4 合并输出,按 apptype 分别对比各自基线              │
+-- └─────────────────────────────────────────────────────────────────────┘
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/3:实验映射(按 apptype 分组) ─────────────────────────────┐
+-- │  新增 apptype 只需追加行,下游逻辑自动适配                           │
+-- │  未列出的桶 → 自动默认为"对照组"                                     │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    -- ── apptype = 4 ──────────────────────────────────────────────────
+    SELECT "4" AS apptype, "ab" AS suffix_group, "实验组:变更str*ros建模目标实验 有问题" AS abcode, "20260413" AS start_dt, "20260415" AS end_dt
+    UNION ALL SELECT "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "20260514"
+    UNION ALL SELECT "4", "ab", "实验组:供给来源加权实验", "20260515", "20260518"
+    UNION ALL SELECT "4", "ab", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT "4", "ab", "实验组:重排移除后处理实验", "20260527", "29991231"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260510"
+    UNION ALL SELECT "4", "01", "对照组:变更str*ros建模目标实验", "20260511", "20260514"
+    UNION ALL SELECT "4", "01", "对照组:DNN模型-调参", "20260515", "20260521"
+    UNION ALL SELECT "4", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "20260512"
+    UNION ALL SELECT "4", "67", "实验组:一年行为个性化品类召回", "20260513", "29991231"
+    UNION ALL SELECT "4", "5d", "实验组:解构特征排序str模型",     "20260314", "20260406"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "20260521"
+    UNION ALL SELECT "4", "5d", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT "4", "5d", "实验组:召回改目标all_rov", "20260523", "29991231"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "34", "实验组:召回剔除低质召回实验", "20260508", "20260514"
+    UNION ALL SELECT "4", "34", "实验组:DNN模型-调参", "20260515", "20260518"
+    UNION ALL SELECT "4", "34", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
+    UNION ALL SELECT "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型",                 "20260407", "20260518"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型-调参",                 "20260519", "20260521"
+    UNION ALL SELECT "4", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT "4", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260523", "29991231"
+    UNION ALL SELECT "4", "2c", "实验组:DNN模型-调参",            "20260413", "20260518"
+    UNION ALL SELECT "4", "2c", "实验组:一年行为个性化品类召回",            "20260519", "20260526"
+    UNION ALL SELECT "4", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT "4", "89", "对照组",                          "20260301", "20260510"
+    UNION ALL SELECT "4", "89", "实验组:变更str*ros建模目标实验",                          "20260511", "20260514"
+    UNION ALL SELECT "4", "89", "实验组:DNN模型-调参",                          "20260515", "20260520"
+    UNION ALL SELECT "4", "89", "实验组:省份热门rov召回-指标修正", "20260521", "20260522"
+    UNION ALL SELECT "4", "89", "实验组:召回加整体配额40%", "20260523", "29991231"
+
+    -- ── apptype = 0 ──────────────────────────────────────────────────
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验", "20260417", "20260429"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260430", "20260517"
+    UNION ALL SELECT "0", "ab", "实验组:一年行为个性化品类召回", "20260518", "29991231"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "0", "01", "对照组:变更str*ros建模目标实验", "20260508", "20260513"
+    UNION ALL SELECT "0", "01", "对照组:DNN模型-调参", "20260514", "20260521"
+    UNION ALL SELECT "0", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "34", "实验组:曝光建模v1+变更str*ros建模目标实验", "20260425", "20260425"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260426", "20260429"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260430", "20260518"
+    UNION ALL SELECT "0", "34", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260417", "20260513"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260514", "20260518"
+    UNION ALL SELECT "0", "67", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "20260521"
+    UNION ALL SELECT "0", "5d", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "20260521"
+    UNION ALL SELECT "0", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260526"
+    UNION ALL SELECT "0", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型-调参",                 "20260508", "20260518"
+    UNION ALL SELECT "0", "2c", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT "0", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT "0", "89", "对照组",                          "20260301", "20260507"
+    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "20260521"
+    UNION ALL SELECT "0", "89", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+)
+-- ┌─ 配置区 2/3:DAU2 基线窗口(5 天均值的日期范围) ─────────────────────┐
+-- │  改基线只需修改这一行,无需改下游逻辑                                │
+-- │  代价:每次跑会多扫该窗口区间的 useractive_log(轻量表,可接受)    │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_base5_window AS
+(
+    SELECT "20260307" AS base_start, "20260311" AS base_end
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") 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
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                -- apptype=4: ab0-ab9; apptype=0: ab0-ab4,ab8,ab9(无 ab5/ab6/ab7)
+                AND     abcode NOT IN ("ab100")
+                AND     (apptype = "4"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab8","ab9"))
+                AND     (apptype = "0"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix, vid
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+-- ECS = 2 * Σ(p_i * rank_i) - 1
+--   p_i    = vid 在桶内曝光占比
+--   rank_i = 按曝光降序的排名(1 起)
+-- 值域 [1, distinct_vid_cnt],越大越分散,越小越头部集中
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,abcode
+                        ,suffix
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, abcode, suffix
+)
+-- 全平台每个 vid 的曝光度(作为 ARP 的 popularity reference)
+-- 注意:不过滤 abcode,让 reference 覆盖全部合法尾号
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, vid
+)
+-- 桶内 ARP (Average Recommendation Popularity):推荐视频的平均热门度
+-- 按桶内曝光量加权:曝光越多的 vid 对 ARP 影响越大
+-- 组合 ECS + ARP 可识别四象限:
+--   高ECS + 低ARP = 分散 + 偏长尾        ✅ 理想
+--   高ECS + 高ARP = 分散 + 头部内部多样化  ⚠️ 需警惕
+--   低ECS + 低ARP = 集中 + 冷门(小众爆发) ❓ 特殊
+--   低ECS + 高ARP = 集中 + 头部            ❌ 模型坍缩
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.abcode
+            ,v.suffix
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.abcode, v.suffix
+)
+-- dau2:按单尾号聚合(当天)
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,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}"
+                AND     apptype IN ("0","4")
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+)
+-- dau2:按 suffix_group 求尾号均值(当天)
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,AVG(dau2) AS dau2
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, abcode, suffix_group
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 N 天均值(由 t_base5_window 配置)
+-- 语义复刻原 hardcoded 版本:每天每组 dau2 = AVG(组内每个尾号 dau2),再跨天 AVG
+-- 注意:不过滤 abcode(基线只看物理桶 suffix_group,不绑实验快照)
+-- ════════════════════════════════════════════════════════════════════════════
+,t_dau2_base5 AS
+(
+    SELECT  apptype
+            ,suffix_group
+            ,AVG(group_day_dau2) AS dau2_base5
+    FROM    (
+                -- 每天每个 suffix_group 的 dau2 = AVG(组内每个 suffix 的 dau2)
+                SELECT  dt
+                        ,apptype
+                        ,suffix_group
+                        ,AVG(suffix_dau2) AS group_day_dau2
+                FROM    (
+                            -- 每天每个尾号的 dau2 = COUNT(DISTINCT mid)
+                            SELECT  SUBSTR(sub.dt,1,8) AS dt
+                                    ,sub.apptype
+                                    ,sg.suffix_group
+                                    ,sub.suffix
+                                    ,COUNT(DISTINCT sub.machinecode) AS suffix_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
+                                        CROSS JOIN t_base5_window w
+                                        WHERE   dt BETWEEN w.base_start AND w.base_end
+                                        AND     apptype IN ("0","4")
+                                        AND     (apptype = "4"
+                                                 OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+                                    ) sub
+                            INNER JOIN t_suffix_group sg
+                            ON      sub.suffix = sg.suffix
+                            GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, sg.suffix_group, sub.suffix
+                        ) t_suf
+                GROUP BY dt, apptype, suffix_group
+            ) t_day
+    GROUP BY apptype, suffix_group
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            -- 合并 ROV = bn_rov + cn_rov + dn_rov(三者分母同为 COUNT(1),可合并)
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            -- 桶内去重 vid 数(ECS 的天然配套)
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix_group, suffix
+)
+-- 按实验组求尾号均值
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.abcode
+            ,b.suffix_group
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            -- ECS 归一化比值:去掉池子大小的影响,纯形态指标
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            -- Gini 系数:快手/Twitter/Netflix 业界标准,数学上 Gini = 1 - ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    GROUP BY b.dt, b.apptype, b.abcode, b.suffix_group
+)
+-- 合并主表 + dau2 + dau_vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,ROUND(b.dau2 / NULLIF(c.dau2_base5, 0), 6) AS dau_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_group = c.suffix_group
+)
+-- ┌─ 配置区 3/3:对照桶(横向对比基准) ─────────────────────────────────┐
+-- │  每行 (apptype, [start_dt,end_dt]) 必须不重叠,保证唯一命中          │
+-- │  切换对照桶时:闭旧行 end_dt + 加新行(SCD2 风格)                   │
+-- │  与 t_experiment_map 的"对照组"行**有意冗余**,作为 diff 基准的      │
+-- │  单一权威源,避免被实验注册改动间接影响                              │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    SELECT "4" AS apptype, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "20260510" AS end_dt
+    UNION ALL SELECT "4", "01", "20260511", "29991231"
+    UNION ALL SELECT "0", "89", "20260101", "20260507"
+    UNION ALL SELECT "0", "01", "20260508", "29991231"
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.dau_vs_5d  AS ctrl_dau_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.abcode
+        ,r.suffix_group
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        -- ── DAU2 纵向对比(vs 历史基线均值) ──
+        ,r.dau_vs_5d
+        -- ── 横向对比:当日各桶 vs 对照桶,公式 = 当前值 / 对照值 - 1 ──
+        ,ROUND(r.dau_vs_5d / NULLIF(ctrl.ctrl_dau_vs_5d, 0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        -- 复合指标:曝光量变化 × ROV变化 的联动效果
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+ORDER BY r.dt DESC, r.apptype, r.abcode, r.suffix_group
+;

+ 10 - 0
tasks/00_尾号实验/base_all_new_v3_汇总_倒数3位.json

@@ -0,0 +1,10 @@
+{
+  "token": "ONZqsxB9BhGH8tt90EScSJT5nHh",
+  "sheet_id": "ePvpL8",
+  "sort": "dt:desc,apptype:asc,suffix_group:asc,source_type:asc,layer_type:asc",
+  "order": {
+      "suffix_group": ["ab", "34", "2c", "67", "01", "5d", "ef", "89"]
+  },
+  "cols": null,
+  "append_cols": false
+}

+ 611 - 0
tasks/00_尾号实验/base_all_new_v3_汇总_倒数3位.sql

@@ -0,0 +1,611 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 倒数第 3 位尾号实验 — apptype=4 单实验(apptype=0 同时输出作 A/A 参考)
+-- [基于 base_all_new_v3_汇总.sql 改造:suffix 取倒数第 3 位 + 实验配置切换]
+--
+-- ┌─ 实验配置 ──────────────────────────────────────────────────────────┐
+-- │  分流位:rootsessionid 倒数第 3 位(hex 0-f)                         │
+-- │  实验产品:apptype = 4                                                │
+-- │  实验尾号:{0, 1} → suffix_group = "01"                              │
+-- │  实验名:实验组:倒数第3位实验                                          │
+-- │  上线日:20260526                                                     │
+-- │  基线期:20260520~20260525(上线日前 6 天均值)                       │
+-- │  对照桶:89(apptype=4/0 通用,全时段;不再按时段切换)              │
+-- └─────────────────────────────────────────────────────────────────────┘
+--
+-- 注意:8x2 hex 桶方案沿用原汇总版("0","1" 已天然成对为 suffix_group="01"),
+--       无需重新分桶;apptype=0 无实验、所有桶均为对照组,作为新维度的 A/A 参考。
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/3:实验映射(按 apptype 分组) ─────────────────────────────┐
+-- │  本文件是倒数第 3 位维度的新实验,原汇总版(倒数第 1 位)的实验映射  │
+-- │  在这里无意义,所以仅保留新实验这一行                                │
+-- │  未列出的桶 → 自动默认为"对照组"                                     │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    SELECT "4" AS apptype, "01" AS suffix_group, "实验组:倒数第3位实验" AS abcode, "20260526" AS start_dt, "29991231" AS end_dt
+)
+-- ┌─ 配置区 2/3:DAU2 基线窗口(5 天均值的日期范围) ─────────────────────┐
+-- │  改基线只需修改这一行,无需改下游逻辑                                │
+-- │  代价:每次跑会多扫该窗口区间的 useractive_log(轻量表,可接受)    │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_base5_window AS
+(
+    SELECT "20260520" AS base_start, "20260525" AS base_end
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") AS abcode
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'), -3, 1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                -- apptype=4: ab0-ab9; apptype=0: ab0-ab4,ab8,ab9(无 ab5/ab6/ab7)
+                AND     abcode NOT IN ("ab100")
+                AND     (apptype = "4"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab8","ab9"))
+                AND     (apptype = "0"
+                         OR abcode IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix, vid
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+-- ECS = 2 * Σ(p_i * rank_i) - 1
+--   p_i    = vid 在桶内曝光占比
+--   rank_i = 按曝光降序的排名(1 起)
+-- 值域 [1, distinct_vid_cnt],越大越分散,越小越头部集中
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,abcode
+                        ,suffix
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, abcode, suffix
+)
+-- 全平台每个 vid 的曝光度(作为 ARP 的 popularity reference)
+-- 注意:不过滤 abcode,让 reference 覆盖全部合法尾号
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, vid
+)
+-- 桶内 ARP (Average Recommendation Popularity):推荐视频的平均热门度
+-- 按桶内曝光量加权:曝光越多的 vid 对 ARP 影响越大
+-- 组合 ECS + ARP 可识别四象限:
+--   高ECS + 低ARP = 分散 + 偏长尾        ✅ 理想
+--   高ECS + 高ARP = 分散 + 头部内部多样化  ⚠️ 需警惕
+--   低ECS + 低ARP = 集中 + 冷门(小众爆发) ❓ 特殊
+--   低ECS + 高ARP = 集中 + 头部            ❌ 模型坍缩
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.abcode
+            ,v.suffix
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.abcode, v.suffix
+)
+-- dau2:按单尾号聚合(当天)
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'), -3, 1) AS suffix
+                FROM    loghubods.useractive_log
+                WHERE   dt="${dt}"
+                AND     apptype IN ("0","4")
+                AND     (apptype = "4"
+                         OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+)
+-- dau2:按 suffix_group 求尾号均值(当天)
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,AVG(dau2) AS dau2
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, abcode, suffix_group
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 N 天均值(由 t_base5_window 配置)
+-- 语义复刻原 hardcoded 版本:每天每组 dau2 = AVG(组内每个尾号 dau2),再跨天 AVG
+-- 注意:不过滤 abcode(基线只看物理桶 suffix_group,不绑实验快照)
+-- ════════════════════════════════════════════════════════════════════════════
+,t_dau2_base5 AS
+(
+    SELECT  apptype
+            ,suffix_group
+            ,AVG(group_day_dau2) AS dau2_base5
+    FROM    (
+                -- 每天每个 suffix_group 的 dau2 = AVG(组内每个 suffix 的 dau2)
+                SELECT  dt
+                        ,apptype
+                        ,suffix_group
+                        ,AVG(suffix_dau2) AS group_day_dau2
+                FROM    (
+                            -- 每天每个尾号的 dau2 = COUNT(DISTINCT mid)
+                            SELECT  SUBSTR(sub.dt,1,8) AS dt
+                                    ,sub.apptype
+                                    ,sg.suffix_group
+                                    ,sub.suffix
+                                    ,COUNT(DISTINCT sub.machinecode) AS suffix_dau2
+                            FROM    (
+                                        SELECT  /*+ MAPJOIN(w) */
+                                                dt
+                                                ,apptype
+                                                ,machinecode
+                                                ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'), -3, 1) AS suffix
+                                        FROM    loghubods.useractive_log
+                                        CROSS JOIN t_base5_window w
+                                        WHERE   dt BETWEEN w.base_start AND w.base_end
+                                        AND     apptype IN ("0","4")
+                                        AND     (apptype = "4"
+                                                 OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+                                    ) sub
+                            INNER JOIN t_suffix_group sg
+                            ON      sub.suffix = sg.suffix
+                            GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, sg.suffix_group, sub.suffix
+                        ) t_suf
+                GROUP BY dt, apptype, suffix_group
+            ) t_day
+    GROUP BY apptype, suffix_group
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            -- 合并 ROV = bn_rov + cn_rov + dn_rov(三者分母同为 COUNT(1),可合并)
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            -- 桶内去重 vid 数(ECS 的天然配套)
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix_group, suffix
+)
+-- 按实验组求尾号均值
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.abcode
+            ,b.suffix_group
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            -- ECS 归一化比值:去掉池子大小的影响,纯形态指标
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            -- Gini 系数:快手/Twitter/Netflix 业界标准,数学上 Gini = 1 - ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    GROUP BY b.dt, b.apptype, b.abcode, b.suffix_group
+)
+-- 合并主表 + dau2 + dau_vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,ROUND(b.dau2 / NULLIF(c.dau2_base5, 0), 6) AS dau_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_group = c.suffix_group
+)
+-- ┌─ 配置区 3/3:对照桶(横向对比基准) ─────────────────────────────────┐
+-- │  本文件实验桶是 "01"(apptype=4),所以 apptype=4 的对照必须不是 "01"。│
+-- │  统一用 "89" 作为对照桶,全时段不切换(倒数第 3 位维度上 8 个桶等价, │
+-- │  挑哪个非实验桶都行;89 与原汇总版前期对齐,便于跨报表参考)          │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    SELECT "4" AS apptype, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "29991231" AS end_dt
+    UNION ALL SELECT "0", "89", "20260101", "29991231"
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.dau_vs_5d  AS ctrl_dau_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.abcode
+        ,r.suffix_group
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        -- ── DAU2 纵向对比(vs 历史基线均值) ──
+        ,r.dau_vs_5d
+        -- ── 横向对比:当日各桶 vs 对照桶,公式 = 当前值 / 对照值 - 1 ──
+        ,ROUND(r.dau_vs_5d / NULLIF(ctrl.ctrl_dau_vs_5d, 0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        -- 复合指标:曝光量变化 × ROV变化 的联动效果
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+ORDER BY r.dt DESC, r.apptype, r.abcode, r.suffix_group
+;

+ 603 - 0
tasks/00_尾号实验/base_all_new_v3_汇总_倒数3位_v2.sql

@@ -0,0 +1,603 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 倒数第 3 位尾号实验 — t_experiment_map 驱动版 (v2)
+-- [基于 base_all_new_v3_汇总_倒数3位.sql 改造]
+--
+-- 与 v1 的关键差异:
+--   1) apptype 过滤不再硬编码 IN ("0","4"),而是跟随 t_experiment_map:
+--        WHERE apptype IN (SELECT DISTINCT apptype FROM t_experiment_map)
+--      → 想加新 apptype 只需在 map 里加一行,下游全部自动适配
+--   2) abcode 仅保留 NOT IN ("ab100"),删除原 v1 的 ab0~ab9 白名单
+--   3) apptype=0 的 A/A 参考已移除(map 里没有就不跑)
+--
+-- ┌─ 实验配置 ──────────────────────────────────────────────────────────┐
+-- │  分流位:rootsessionid 倒数第 3 位(hex 0-f)                         │
+-- │  实验产品:apptype = 4                                                │
+-- │  实验尾号:{0, 1} → suffix_group = "01"                              │
+-- │  实验名:实验组:倒数第3位实验                                          │
+-- │  上线日:20260526                                                     │
+-- │  基线期:20260520~20260525                                            │
+-- │  对照桶:见 t_ctrl_bucket                                            │
+-- └─────────────────────────────────────────────────────────────────────┘
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/3:实验映射(apptype 的唯一来源) ──────────────────────────┐
+-- │  ★ 现在 t_experiment_map 同时承担两个职责:                          │
+-- │    a) 给桶打实验标签(原职责)                                       │
+-- │    b) 决定整个文件跑哪些 apptype(新增)                             │
+-- │  → 加 apptype 直接在这里追加行即可                                   │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    SELECT "4" AS apptype, "01" AS suffix_group, "实验组:倒数第3位实验" AS abcode, "20260526" AS start_dt, "29991231" AS end_dt
+)
+-- ┌─ 配置区 2/3:DAU2 基线窗口 ──────────────────────────────────────────┐
+,t_base5_window AS
+(
+    SELECT "20260520" AS base_start, "20260525" AS base_end
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") AS abcode
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'), -3, 1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   dt="${dt}"
+                AND     apptype IN (SELECT DISTINCT apptype FROM t_experiment_map)
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix, vid
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+-- ECS = 2 * Σ(p_i * rank_i) - 1
+--   p_i    = vid 在桶内曝光占比
+--   rank_i = 按曝光降序的排名(1 起)
+-- 值域 [1, distinct_vid_cnt],越大越分散,越小越头部集中
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,abcode
+                        ,suffix
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, abcode, suffix
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, abcode, suffix
+)
+-- 全平台每个 vid 的曝光度(作为 ARP 的 popularity reference)
+-- 注意:不过滤 abcode,让 reference 覆盖全部合法尾号
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, vid
+)
+-- 桶内 ARP (Average Recommendation Popularity):推荐视频的平均热门度
+-- 按桶内曝光量加权:曝光越多的 vid 对 ARP 影响越大
+-- 组合 ECS + ARP 可识别四象限:
+--   高ECS + 低ARP = 分散 + 偏长尾        ✅ 理想
+--   高ECS + 高ARP = 分散 + 头部内部多样化  ⚠️ 需警惕
+--   低ECS + 低ARP = 集中 + 冷门(小众爆发) ❓ 特殊
+--   低ECS + 高ARP = 集中 + 头部            ❌ 模型坍缩
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.abcode
+            ,v.suffix
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.abcode, v.suffix
+)
+-- dau2:按单尾号聚合(当天)
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,machinecode
+                        ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'), -3, 1) AS suffix
+                FROM    loghubods.useractive_log
+                WHERE   dt="${dt}"
+                AND     apptype IN (SELECT DISTINCT apptype FROM t_experiment_map)
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+)
+-- dau2:按 suffix_group 求尾号均值(当天)
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,AVG(dau2) AS dau2
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, abcode, suffix_group
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 N 天均值(由 t_base5_window 配置)
+-- 语义复刻原 hardcoded 版本:每天每组 dau2 = AVG(组内每个尾号 dau2),再跨天 AVG
+-- 注意:不过滤 abcode(基线只看物理桶 suffix_group,不绑实验快照)
+-- ════════════════════════════════════════════════════════════════════════════
+,t_dau2_base5 AS
+(
+    SELECT  apptype
+            ,suffix_group
+            ,AVG(group_day_dau2) AS dau2_base5
+    FROM    (
+                -- 每天每个 suffix_group 的 dau2 = AVG(组内每个 suffix 的 dau2)
+                SELECT  dt
+                        ,apptype
+                        ,suffix_group
+                        ,AVG(suffix_dau2) AS group_day_dau2
+                FROM    (
+                            -- 每天每个尾号的 dau2 = COUNT(DISTINCT mid)
+                            SELECT  SUBSTR(sub.dt,1,8) AS dt
+                                    ,sub.apptype
+                                    ,sg.suffix_group
+                                    ,sub.suffix
+                                    ,COUNT(DISTINCT sub.machinecode) AS suffix_dau2
+                            FROM    (
+                                        SELECT  /*+ MAPJOIN(w) */
+                                                dt
+                                                ,apptype
+                                                ,machinecode
+                                                ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'), -3, 1) AS suffix
+                                        FROM    loghubods.useractive_log
+                                        CROSS JOIN t_base5_window w
+                                        WHERE   dt BETWEEN w.base_start AND w.base_end
+                                        AND     apptype IN (SELECT DISTINCT apptype FROM t_experiment_map)
+                                    ) sub
+                            INNER JOIN t_suffix_group sg
+                            ON      sub.suffix = sg.suffix
+                            GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, sg.suffix_group, sub.suffix
+                        ) t_suf
+                GROUP BY dt, apptype, suffix_group
+            ) t_day
+    GROUP BY apptype, suffix_group
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            -- 合并 ROV = bn_rov + cn_rov + dn_rov(三者分母同为 COUNT(1),可合并)
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            -- 桶内去重 vid 数(ECS 的天然配套)
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, abcode, suffix_group, suffix
+)
+-- 按实验组求尾号均值
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.abcode
+            ,b.suffix_group
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            -- ECS 归一化比值:去掉池子大小的影响,纯形态指标
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            -- Gini 系数:快手/Twitter/Netflix 业界标准,数学上 Gini = 1 - ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    GROUP BY b.dt, b.apptype, b.abcode, b.suffix_group
+)
+-- 合并主表 + dau2 + dau_vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,ROUND(b.dau2 / NULLIF(c.dau2_base5, 0), 6) AS dau_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_group = c.suffix_group
+)
+-- ┌─ 配置区 3/3:对照桶(横向对比基准) ─────────────────────────────────┐
+-- │  apptype=4 实验桶是 "01",对照统一用 "89"(倒数第 3 位维度上 8 个     │
+-- │  桶等价,挑哪个非实验桶都行)。t_experiment_map 加新 apptype 时,    │
+-- │  这里也要同步加一行。                                                │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    SELECT "4" AS apptype, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "29991231" AS end_dt
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.dau_vs_5d  AS ctrl_dau_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.abcode
+        ,r.suffix_group
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        -- ── DAU2 纵向对比(vs 历史基线均值) ──
+        ,r.dau_vs_5d
+        -- ── 横向对比:当日各桶 vs 对照桶,公式 = 当前值 / 对照值 - 1 ──
+        ,ROUND(r.dau_vs_5d / NULLIF(ctrl.ctrl_dau_vs_5d, 0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        -- 复合指标:曝光量变化 × ROV变化 的联动效果
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+ORDER BY r.dt DESC, r.apptype, r.abcode, r.suffix_group
+;

+ 720 - 0
tasks/00_尾号实验/base_all_new_v3_汇总_通用.sql

@@ -0,0 +1,720 @@
+-- ════════════════════════════════════════════════════════════════════════════
+-- 尾号实验汇总 — 多 suffix_pos 通用版
+-- [合并 base_all_new_v3_汇总.sql(倒1位) + base_all_new_v3_汇总_倒数3位_v2.sql(倒3位)]
+--
+-- 核心抽象:
+--   ★ suffix_pos 从"文件级 hardcoded" → 提升为"数据维度"
+--     - t_experiment_map 每行携带 suffix_pos
+--     - 派生 t_active_dim = DISTINCT (apptype, suffix_pos) 用于 explode
+--     - 一条曝光按 apptype 命中的 active suffix_pos 数 explode N 倍
+--     - 所有聚合按 (apptype, suffix_pos, ...) 分组,partition 之间独立
+--   ★ t_ctrl_bucket 也按 (apptype, suffix_pos) 分别配对照桶
+--
+-- ┌─ 当前注册的实验维度 ─────────────────────────────────────────────────┐
+-- │  suffix_pos = -1(倒数第 1 位):apptype = 0 / 4,多个历史实验      │
+-- │  suffix_pos = -3(倒数第 3 位):apptype = 4,"实验组:倒数第3位实验"│
+-- │  新增维度只需在 t_experiment_map 加行 + 在 t_ctrl_bucket 加对照桶  │
+-- └─────────────────────────────────────────────────────────────────────┘
+-- ════════════════════════════════════════════════════════════════════════════
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+-- ┌─ 配置区 1/3:实验映射(按 apptype × suffix_pos × suffix_group 分组) ─┐
+-- │  ★ 每行多了 suffix_pos:定义这条实验从 rootsessionid 的哪一位切分    │
+-- │  新增 apptype 或新分流位置只需在这里加行,下游自动适配                │
+-- │  未列出的桶 → 自动默认为"对照组"                                     │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_experiment_map AS
+(
+    -- ════════ suffix_pos = -1(倒数第 1 位) ════════
+    -- ── apptype = 4 ──────────────────────────────────────────────────
+    SELECT -1 AS suffix_pos, "4" AS apptype, "ab" AS suffix_group, "实验组:变更str*ros建模目标实验 有问题" AS abcode, "20260413" AS start_dt, "20260415" AS end_dt
+    UNION ALL SELECT -1, "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT -1, "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "20260514"
+    UNION ALL SELECT -1, "4", "ab", "实验组:供给来源加权实验", "20260515", "20260518"
+    UNION ALL SELECT -1, "4", "ab", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT -1, "4", "ab", "实验组:重排移除后处理实验", "20260527", "29991231"
+    UNION ALL SELECT -1, "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT -1, "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260510"
+    UNION ALL SELECT -1, "4", "01", "对照组:变更str*ros建模目标实验", "20260511", "20260514"
+    UNION ALL SELECT -1, "4", "01", "对照组:DNN模型-调参", "20260515", "20260521"
+    UNION ALL SELECT -1, "4", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT -1, "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT -1, "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "20260512"
+    UNION ALL SELECT -1, "4", "67", "实验组:一年行为个性化品类召回", "20260513", "29991231"
+    UNION ALL SELECT -1, "4", "5d", "实验组:解构特征排序str模型",     "20260314", "20260406"
+    UNION ALL SELECT -1, "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT -1, "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT -1, "4", "5d", "实验组:DNN模型-调参",     "20260508", "20260521"
+    UNION ALL SELECT -1, "4", "5d", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT -1, "4", "5d", "实验组:召回改目标all_rov", "20260523", "29991231"
+    UNION ALL SELECT -1, "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT -1, "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT -1, "4", "34", "实验组:召回剔除低质召回实验", "20260508", "20260514"
+    UNION ALL SELECT -1, "4", "34", "实验组:DNN模型-调参", "20260515", "20260518"
+    UNION ALL SELECT -1, "4", "34", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT -1, "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
+    UNION ALL SELECT -1, "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
+    UNION ALL SELECT -1, "4", "ef", "实验组:DNN模型",                 "20260407", "20260518"
+    UNION ALL SELECT -1, "4", "ef", "实验组:DNN模型-调参",                 "20260519", "20260521"
+    UNION ALL SELECT -1, "4", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260522"
+    UNION ALL SELECT -1, "4", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260523", "29991231"
+    UNION ALL SELECT -1, "4", "2c", "实验组:DNN模型-调参",            "20260413", "20260518"
+    UNION ALL SELECT -1, "4", "2c", "实验组:一年行为个性化品类召回",            "20260519", "20260526"
+    UNION ALL SELECT -1, "4", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT -1, "4", "89", "对照组",                          "20260301", "20260510"
+    UNION ALL SELECT -1, "4", "89", "实验组:变更str*ros建模目标实验",                          "20260511", "20260514"
+    UNION ALL SELECT -1, "4", "89", "实验组:DNN模型-调参",                          "20260515", "20260520"
+    UNION ALL SELECT -1, "4", "89", "实验组:省份热门rov召回-指标修正", "20260521", "20260522"
+    UNION ALL SELECT -1, "4", "89", "实验组:召回加整体配额40%", "20260523", "29991231"
+    -- ── apptype = 0 ──────────────────────────────────────────────────
+    UNION ALL SELECT -1, "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
+    UNION ALL SELECT -1, "0", "ab", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT -1, "0", "ab", "实验组:变更str*ros建模目标实验", "20260417", "20260429"
+    UNION ALL SELECT -1, "0", "ab", "实验组:DNN模型-调参", "20260430", "20260517"
+    UNION ALL SELECT -1, "0", "ab", "实验组:一年行为个性化品类召回", "20260518", "29991231"
+    UNION ALL SELECT -1, "0", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT -1, "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT -1, "0", "01", "对照组:变更str*ros建模目标实验", "20260508", "20260513"
+    UNION ALL SELECT -1, "0", "01", "对照组:DNN模型-调参", "20260514", "20260521"
+    UNION ALL SELECT -1, "0", "01", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT -1, "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT -1, "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT -1, "0", "34", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT -1, "0", "34", "实验组:曝光建模v1+变更str*ros建模目标实验", "20260425", "20260425"
+    UNION ALL SELECT -1, "0", "34", "实验组:变更str*ros建模目标实验", "20260426", "20260429"
+    UNION ALL SELECT -1, "0", "34", "实验组:DNN模型-调参", "20260430", "20260518"
+    UNION ALL SELECT -1, "0", "34", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT -1, "0", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT -1, "0", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "0", "67", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT -1, "0", "67", "实验组:变更str*ros建模目标实验", "20260417", "20260513"
+    UNION ALL SELECT -1, "0", "67", "实验组:DNN模型-调参", "20260514", "20260518"
+    UNION ALL SELECT -1, "0", "67", "实验组:一年行为个性化品类召回", "20260519", "29991231"
+    UNION ALL SELECT -1, "0", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT -1, "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT -1, "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT -1, "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT -1, "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "20260521"
+    UNION ALL SELECT -1, "0", "5d", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+    UNION ALL SELECT -1, "0", "ef", "实验组:DNN模型-调参",            "20260410", "20260521"
+    UNION ALL SELECT -1, "0", "ef", "实验组:一年行为个性化品类召回", "20260522", "20260526"
+    UNION ALL SELECT -1, "0", "ef", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT -1, "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
+    UNION ALL SELECT -1, "0", "2c", "实验组:DNN模型-调参",                 "20260508", "20260518"
+    UNION ALL SELECT -1, "0", "2c", "实验组:一年行为个性化品类召回", "20260519", "20260526"
+    UNION ALL SELECT -1, "0", "2c", "实验组:召回改目标all_rov+删非低效非rov热度", "20260527", "29991231"
+    UNION ALL SELECT -1, "0", "89", "对照组",                          "20260301", "20260507"
+    UNION ALL SELECT -1, "0", "89", "实验组:DNN模型-调参",                          "20260508", "20260521"
+    UNION ALL SELECT -1, "0", "89", "实验组:一年行为个性化品类召回", "20260522", "29991231"
+
+    -- ════════ suffix_pos = -3(倒数第 3 位) ════════
+    UNION ALL SELECT -3, "4", "01", "实验组:倒数第3位实验", "20260526", "29991231"
+)
+-- 派生维度:activelist = DISTINCT (apptype, suffix_pos)
+-- → INNER JOIN 这张表实现一行曝光按 apptype 命中的 active 位置 explode N 倍
+,t_active_dim AS
+(
+    SELECT DISTINCT apptype, suffix_pos FROM t_experiment_map
+)
+-- ┌─ 配置区 2/3:DAU2 基线窗口 ──────────────────────────────────────────┐
+-- │  改基线只需修改这一行,无需改下游逻辑                                │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_base5_window AS
+(
+    SELECT "20260520" AS base_start, "20260525" AS base_end
+)
+,t_base AS
+(
+    SELECT  sub.*
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") AS abcode
+    FROM    (
+                SELECT  /*+ MAPJOIN(d) */
+                        a.dt
+                        ,a.apptype
+                        ,d.suffix_pos
+                        ,SUBSTR(GET_JSON_OBJECT(a.extend,'$.rootsessionid'), d.suffix_pos, 1) AS suffix
+                        ,CASE   WHEN page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                                WHEN page IN ("回流页","其他") THEN "非推荐"
+                                ELSE "其他"
+                        END AS page
+                        ,a.mid
+                        ,a.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
+                        ,cc.cn
+                        ,cc.c1
+                        ,dd.dn
+                        ,dd.d1
+                FROM    loghubods.dwd_recsys_alg_exposure_base_20250108 a
+                -- ★ 关键 explode:一行曝光按 active 位置数复制 N 行
+                INNER JOIN t_active_dim d
+                ON      a.apptype = d.apptype
+                LEFT JOIN   (
+                                -- c1/cn:分享后被点击的回流 UV
+                                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 c1
+                                FROM    (
+                                            SELECT  DISTINCT machinecode
+                                                    ,shareobjectid AS videoid
+                                                    ,recomTraceId
+                                                    ,subsessionid
+                                                    ,sharedepth
+                                                    ,shareid
+                                            FROM    loghubods.user_share_log
+                                            WHERE   dt = '${dt}'
+                                            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 = '${dt}'
+                                                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 = '${dt}'
+                                                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 = '${dt}'
+                                                AND     topic = 'click'
+                                            ) b2
+                                ON      b1.shareid = b2.rootshareid
+                                GROUP BY a.machinecode
+                                         ,a.subsessionid
+                                         ,a.videoid
+                            ) cc
+                ON      a.mid = cc.mid
+                AND     a.subsessionid = cc.subsessionid
+                AND     a.vid = cc.vid
+                LEFT JOIN   (
+                                -- d1/dn:下一条视频带来的回流
+                                SELECT  *
+                                        ,LAG(回流,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) AS dn
+                                        ,LAG(回流1,1,0) OVER (PARTITION BY mid,subsessionid ORDER BY rn DESC) 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 ASC) AS rn
+                                            FROM    (
+                                                        SELECT  *
+                                                        FROM    (
+                                                                    SELECT  DISTINCT mid
+                                                                            ,subsessionid
+                                                                            ,videoid
+                                                                            ,logtimestamp
+                                                                            ,ROW_NUMBER() OVER (PARTITION BY mid,subsessionid,videoid ORDER BY logtimestamp ASC) AS rn
+                                                                    FROM    loghubods.video_action_log_rp
+                                                                    WHERE   dt = '${dt}'
+                                                                    AND     businesstype = 'videoView'
+                                                                    AND     pagesource REGEXP 'category$|recommend$|-pages/user-videos-detail$'
+                                                                )
+                                                        WHERE   rn = 1
+                                                    ) a
+                                            LEFT JOIN   (
+                                                            SELECT  DISTINCT machinecode
+                                                                    ,shareobjectid AS videoid
+                                                                    ,recomTraceId
+                                                                    ,subsessionid
+                                                                    ,sharedepth
+                                                                    ,shareid
+                                                                    ,clienttimestamp
+                                                            FROM    loghubods.user_share_log
+                                                            WHERE   dt = '${dt}'
+                                                            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 = '${dt}'
+                                                            AND     topic = 'click'
+                                                        ) c
+                                            ON      b.shareid = c.rootshareid
+                                            GROUP BY a.mid
+                                                     ,a.subsessionid
+                                                     ,a.videoid
+                                                     ,a.logtimestamp
+                                        )
+                            ) dd
+                ON      a.mid = dd.mid
+                AND     a.subsessionid = dd.subsessionid
+                AND     a.vid = dd.vid
+                WHERE   a.dt="${dt}"
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页","回流页","其他")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    -- INNER JOIN: 合法尾号(在 16 个 hex 里)才进分析;防御异常数据
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    -- LEFT JOIN: 可无实验匹配,此时 m.abcode 为 NULL → COALESCE 为"对照组"
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sub.suffix_pos = m.suffix_pos
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+)
+-- 桶内每个 vid 的曝光数(ECS / ARP 的共同中间件,避免重复扫 t_base)
+,t_vid_exp AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_pos
+            ,abcode
+            ,suffix
+            ,vid
+            ,COUNT(1) AS vid_exp_cnt
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, suffix_pos, abcode, suffix, vid
+)
+-- 桶内 ECS (Effective Catalog Size):曝光实际"相当于推了多少条视频"
+,t_bucket_ecs AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_pos
+            ,abcode
+            ,suffix
+            ,2 * SUM(p * rn) - 1 AS ecs
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,suffix_pos
+                        ,abcode
+                        ,suffix
+                        ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
+                            PARTITION BY dt, apptype, suffix_pos, abcode, suffix
+                        ) AS p
+                        ,ROW_NUMBER() OVER (
+                            PARTITION BY dt, apptype, suffix_pos, abcode, suffix
+                            ORDER BY vid_exp_cnt DESC
+                        ) AS rn
+                FROM    t_vid_exp
+            ) t
+    GROUP BY dt, apptype, suffix_pos, abcode, suffix
+)
+-- 全平台每个 vid 的曝光度(按 suffix_pos 分开,因为同一 vid 在不同位置切分下都算"全平台")
+,t_vid_global_pop AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_pos
+            ,vid
+            ,COUNT(1) AS vid_global_pop
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, suffix_pos, vid
+)
+-- 桶内 ARP (Average Recommendation Popularity)
+,t_bucket_arp AS
+(
+    SELECT  v.dt
+            ,v.apptype
+            ,v.suffix_pos
+            ,v.abcode
+            ,v.suffix
+            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
+    FROM    t_vid_exp v
+    LEFT JOIN t_vid_global_pop g
+    ON      v.dt = g.dt
+    AND     v.apptype = g.apptype
+    AND     v.suffix_pos = g.suffix_pos
+    AND     v.vid = g.vid
+    GROUP BY v.dt, v.apptype, v.suffix_pos, v.abcode, v.suffix
+)
+-- dau2:按单尾号聚合(当天)
+,t_dau2_bucket AS
+(
+    SELECT  SUBSTR(sub.dt,1,8) AS dt
+            ,sub.apptype
+            ,sub.suffix_pos
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sg.suffix_group
+            ,sub.suffix
+            ,COUNT(DISTINCT sub.machinecode) AS dau2
+    FROM    (
+                SELECT  /*+ MAPJOIN(d) */
+                        u.dt
+                        ,u.apptype
+                        ,u.machinecode
+                        ,d.suffix_pos
+                        ,SUBSTR(GET_JSON_OBJECT(u.extparams,'$.rootSessionId'), d.suffix_pos, 1) AS suffix
+                FROM    loghubods.useractive_log u
+                INNER JOIN t_active_dim d
+                ON      u.apptype = d.apptype
+                WHERE   u.dt="${dt}"
+                -- apptype=4 用 dwd 表的 abcode 标识实验,不依赖 useractive_log 的 ab_test003
+                -- apptype=0 才需要这一层防御性过滤
+                AND     (u.apptype = "4"
+                         OR GET_JSON_OBJECT(u.extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sub.suffix_pos = m.suffix_pos
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, sub.suffix_pos, COALESCE(m.abcode,"对照组"), sg.suffix_group, sub.suffix
+)
+-- dau2:按 suffix_group 求尾号均值(当天)
+,t_dau2 AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_pos
+            ,abcode
+            ,suffix_group
+            ,AVG(dau2) AS dau2
+    FROM    t_dau2_bucket
+    GROUP BY dt, apptype, suffix_pos, abcode, suffix_group
+)
+-- ════════════════════════════════════════════════════════════════════════════
+-- 基线对比层:DAU2 历史 N 天均值(由 t_base5_window 配置)
+-- 注意:不过滤 abcode(基线只看物理桶 suffix_group × suffix_pos,不绑实验快照)
+-- ════════════════════════════════════════════════════════════════════════════
+,t_dau2_base5 AS
+(
+    SELECT  apptype
+            ,suffix_pos
+            ,suffix_group
+            ,AVG(group_day_dau2) AS dau2_base5
+    FROM    (
+                SELECT  dt
+                        ,apptype
+                        ,suffix_pos
+                        ,suffix_group
+                        ,AVG(suffix_dau2) AS group_day_dau2
+                FROM    (
+                            SELECT  SUBSTR(sub.dt,1,8) AS dt
+                                    ,sub.apptype
+                                    ,sub.suffix_pos
+                                    ,sg.suffix_group
+                                    ,sub.suffix
+                                    ,COUNT(DISTINCT sub.machinecode) AS suffix_dau2
+                            FROM    (
+                                        SELECT  /*+ MAPJOIN(w, d) */
+                                                u.dt
+                                                ,u.apptype
+                                                ,u.machinecode
+                                                ,d.suffix_pos
+                                                ,SUBSTR(GET_JSON_OBJECT(u.extparams,'$.rootSessionId'), d.suffix_pos, 1) AS suffix
+                                        FROM    loghubods.useractive_log u
+                                        CROSS JOIN t_base5_window w
+                                        INNER JOIN t_active_dim d
+                                        ON      u.apptype = d.apptype
+                                        WHERE   u.dt BETWEEN w.base_start AND w.base_end
+                                        AND     (u.apptype = "4"
+                                                 OR GET_JSON_OBJECT(u.extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+                                    ) sub
+                            INNER JOIN t_suffix_group sg
+                            ON      sub.suffix = sg.suffix
+                            GROUP BY SUBSTR(sub.dt,1,8), sub.apptype, sub.suffix_pos, sg.suffix_group, sub.suffix
+                        ) t_suf
+                GROUP BY dt, apptype, suffix_pos, suffix_group
+            ) t_day
+    GROUP BY apptype, suffix_pos, suffix_group
+)
+-- 按单尾号聚合(尾号内 UV 去重)
+,t_bucket AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_pos
+            ,abcode
+            ,suffix_group
+            ,suffix
+            ,COALESCE(COUNT(1) / COUNT(DISTINCT mid),0) AS exp_per_dau
+            ,COALESCE(SUM(is_share) / COUNT(1),0) AS str_one
+            ,COALESCE(SUM(return_n_uv) / SUM(is_share),0) AS ros_one
+            ,COALESCE(SUM(share_cnt) / COUNT(1),0) AS str
+            ,COALESCE(SUM(return_n_uv) / SUM(share_cnt),0) AS ros
+            ,COALESCE(SUM(is_return_1) / COUNT(1),0) AS str_plus
+            ,COALESCE(SUM(return_n_uv) / SUM(is_return_1),0) AS ros_minus
+            ,COALESCE(SUM(return_n_uv) / COUNT(1),0) AS bn_rov
+            ,COALESCE(SUM(c1) / COUNT(1),0) AS c1_rov
+            ,COALESCE(SUM(cn) / COUNT(1),0) AS cn_rov
+            ,COALESCE(SUM(d1) / COUNT(1),0) AS d1_rov
+            ,COALESCE(SUM(dn) / COUNT(1),0) AS dn_rov
+            ,COALESCE((SUM(return_n_uv) + SUM(cn) + SUM(dn)) / COUNT(1),0) AS total_rov
+            ,COALESCE(SUM(new_exposure_cnt) / COUNT(1),0) AS vovh24
+            ,COUNT(DISTINCT mid) AS dau
+            ,COUNT(1) AS exp
+            ,COUNT(DISTINCT vid) AS distinct_vid_cnt
+            ,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
+            ,COALESCE(SUM(cn),0) AS cn
+            ,COALESCE(SUM(c1),0) AS c1
+            ,COALESCE(SUM(dn),0) AS dn
+            ,COALESCE(SUM(d1),0) AS d1
+    FROM    t_base
+    WHERE   page = "推荐"
+    GROUP BY dt, apptype, suffix_pos, abcode, suffix_group, suffix
+)
+-- 按实验组求尾号均值
+,t_metrics AS
+(
+    SELECT  b.dt
+            ,b.apptype
+            ,b.suffix_pos
+            ,b.abcode
+            ,b.suffix_group
+            ,ROUND(AVG(b.exp_per_dau),2) AS exp_per_dau
+            ,ROUND(AVG(b.str_one),6) AS str_one
+            ,ROUND(AVG(b.ros_one),6) AS ros_one
+            ,ROUND(AVG(b.str),6) AS str
+            ,ROUND(AVG(b.ros),6) AS ros
+            ,ROUND(AVG(b.str_plus),6) AS str_plus
+            ,ROUND(AVG(b.ros_minus),6) AS ros_minus
+            ,ROUND(AVG(b.bn_rov),6) AS bn_rov
+            ,ROUND(AVG(b.c1_rov),6) AS c1_rov
+            ,ROUND(AVG(b.cn_rov),6) AS cn_rov
+            ,ROUND(AVG(b.d1_rov),6) AS d1_rov
+            ,ROUND(AVG(b.dn_rov),6) AS dn_rov
+            ,ROUND(AVG(b.total_rov),6) AS total_rov
+            ,ROUND(AVG(b.vovh24),6) AS vovh24
+            ,AVG(b.dau) AS dau
+            ,AVG(b.exp) AS exp
+            ,ROUND(AVG(b.distinct_vid_cnt),0) AS distinct_vid_cnt
+            ,ROUND(AVG(e.ecs),1) AS ecs
+            ,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS ecs_ratio
+            ,ROUND(1 - AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt),0),6) AS gini
+            ,ROUND(AVG(a.arp),0) AS arp
+            ,AVG(b.is_share) AS is_share
+            ,AVG(b.share_cnt) AS share_cnt
+            ,AVG(b.is_return_1) AS is_return_1
+            ,AVG(b.return_n_uv) AS return_n_uv
+            ,AVG(b.viewh24) AS viewh24
+            ,AVG(b.return_n_uv_noself) AS return_n_uv_noself
+            ,AVG(b.cn) AS cn
+            ,AVG(b.c1) AS c1
+            ,AVG(b.dn) AS dn
+            ,AVG(b.d1) AS d1
+            ,WM_CONCAT(DISTINCT ',',b.suffix) AS suffix
+    FROM    t_bucket b
+    LEFT JOIN t_bucket_ecs e
+    ON      b.dt = e.dt
+    AND     b.apptype = e.apptype
+    AND     b.suffix_pos = e.suffix_pos
+    AND     b.abcode = e.abcode
+    AND     b.suffix = e.suffix
+    LEFT JOIN t_bucket_arp a
+    ON      b.dt = a.dt
+    AND     b.apptype = a.apptype
+    AND     b.suffix_pos = a.suffix_pos
+    AND     b.abcode = a.abcode
+    AND     b.suffix = a.suffix
+    GROUP BY b.dt, b.apptype, b.suffix_pos, b.abcode, b.suffix_group
+)
+-- 合并主表 + dau2 + dau_vs_5d
+,t_combined AS
+(
+    SELECT  a.*
+            ,b.dau2
+            ,ROUND(b.dau2 / NULLIF(c.dau2_base5, 0), 6) AS dau_vs_5d
+    FROM    t_metrics a
+    LEFT JOIN t_dau2 b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.suffix_pos = b.suffix_pos
+    AND     a.abcode = b.abcode
+    AND     a.suffix_group = b.suffix_group
+    LEFT JOIN t_dau2_base5 c
+    ON      a.apptype = c.apptype
+    AND     a.suffix_pos = c.suffix_pos
+    AND     a.suffix_group = c.suffix_group
+)
+-- ┌─ 配置区 3/3:对照桶(横向对比基准,按 apptype × suffix_pos 切分) ────┐
+-- │  每行 (apptype, suffix_pos, [start_dt,end_dt]) 必须不重叠            │
+-- │  ★ suffix_pos 不同 → 物理意义不同的桶,要分别配                       │
+-- └──────────────────────────────────────────────────────────────────────┘
+,t_ctrl_bucket AS
+(
+    -- suffix_pos = -1(沿用 base_all_new_v3_汇总.sql 历史配置)
+    SELECT "4" AS apptype, -1 AS suffix_pos, "89" AS ctrl_suffix_group, "20260101" AS start_dt, "20260510" AS end_dt
+    UNION ALL SELECT "4", -1, "01", "20260511", "29991231"
+    UNION ALL SELECT "0", -1, "89", "20260101", "20260507"
+    UNION ALL SELECT "0", -1, "01", "20260508", "29991231"
+    -- suffix_pos = -3(实验桶是 01,对照统一用 89)
+    UNION ALL SELECT "4", -3, "89", "20260101", "29991231"
+)
+-- 对照桶每日指标,作为横向对比基准(按 apptype × suffix_pos × dt 动态选取)
+,t_ctrl AS
+(
+    SELECT  c.dt
+            ,c.apptype
+            ,c.suffix_pos
+            ,c.dau_vs_5d  AS ctrl_dau_vs_5d
+            ,c.exp        AS ctrl_exp
+            ,c.exp_per_dau AS ctrl_exp_per_dau
+            ,c.str_one    AS ctrl_str_one
+            ,c.ros_one    AS ctrl_ros_one
+            ,c.str        AS ctrl_str
+            ,c.ros        AS ctrl_ros
+            ,c.vovh24     AS ctrl_vovh24
+            ,c.str_plus   AS ctrl_str_plus
+            ,c.ros_minus  AS ctrl_ros_minus
+            ,c.bn_rov     AS ctrl_bn_rov
+            ,c.c1_rov     AS ctrl_c1_rov
+            ,c.cn_rov     AS ctrl_cn_rov
+            ,c.d1_rov     AS ctrl_d1_rov
+            ,c.dn_rov     AS ctrl_dn_rov
+            ,c.total_rov  AS ctrl_total_rov
+            ,c.ecs        AS ctrl_ecs
+            ,c.ecs_ratio  AS ctrl_ecs_ratio
+            ,c.arp        AS ctrl_arp
+    FROM    t_combined c
+    INNER JOIN t_ctrl_bucket cb
+    ON      c.apptype = cb.apptype
+    AND     c.suffix_pos = cb.suffix_pos
+    AND     c.suffix_group = cb.ctrl_suffix_group
+    AND     c.dt BETWEEN cb.start_dt AND cb.end_dt
+)
+-- 最终输出:原始指标 + 基线对比差值(后缀 _diff = 当前值 / 基线桶值 - 1)
+SELECT  r.dt
+        ,r.apptype
+        ,r.suffix_pos
+        ,r.abcode
+        ,r.suffix_group
+        ,r.suffix
+        -- ── 原始指标 ──
+        ,r.exp_per_dau
+        ,r.str_one
+        ,r.ros_one
+        ,r.str
+        ,r.ros
+        ,r.str_plus
+        ,r.ros_minus
+        ,r.bn_rov
+        ,r.c1_rov
+        ,r.cn_rov
+        ,r.d1_rov
+        ,r.dn_rov
+        ,r.total_rov
+        ,r.vovh24
+        ,r.dau
+        ,r.exp
+        ,r.distinct_vid_cnt
+        ,r.ecs
+        ,r.ecs_ratio
+        ,r.gini
+        ,r.arp
+        ,r.is_share
+        ,r.share_cnt
+        ,r.is_return_1
+        ,r.return_n_uv
+        ,r.viewh24
+        ,r.return_n_uv_noself
+        ,r.cn
+        ,r.c1
+        ,r.dn
+        ,r.d1
+        ,r.dau2
+        -- ── DAU2 纵向对比(vs 历史基线均值) ──
+        ,r.dau_vs_5d
+        -- ── 横向对比:当日各桶 vs 对照桶,公式 = 当前值 / 对照值 - 1 ──
+        ,ROUND(r.dau_vs_5d / NULLIF(ctrl.ctrl_dau_vs_5d, 0) - 1, 6) AS dau_vs_5d_diff
+        ,ROUND(r.exp / NULLIF(ctrl.ctrl_exp, 0) - 1, 6) AS exp_diff
+        ,ROUND((1 + r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1)
+             * (1 + r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1)
+             - 1, 6) AS exp_rov_combined_diff
+        ,ROUND(r.exp_per_dau / NULLIF(ctrl.ctrl_exp_per_dau, 0) - 1, 6) AS exp_per_dau_diff
+        ,ROUND(r.str_one / NULLIF(ctrl.ctrl_str_one, 0) - 1, 6) AS str_one_diff
+        ,ROUND(r.ros_one / NULLIF(ctrl.ctrl_ros_one, 0) - 1, 6) AS ros_one_diff
+        ,ROUND(r.str / NULLIF(ctrl.ctrl_str, 0) - 1, 6) AS str_diff
+        ,ROUND(r.ros / NULLIF(ctrl.ctrl_ros, 0) - 1, 6) AS ros_diff
+        ,ROUND(r.vovh24 / NULLIF(ctrl.ctrl_vovh24, 0) - 1, 6) AS vovh24_diff
+        ,ROUND(r.str_plus / NULLIF(ctrl.ctrl_str_plus, 0) - 1, 6) AS str_plus_diff
+        ,ROUND(r.ros_minus / NULLIF(ctrl.ctrl_ros_minus, 0) - 1, 6) AS ros_minus_diff
+        ,ROUND(r.bn_rov / NULLIF(ctrl.ctrl_bn_rov, 0) - 1, 6) AS bn_rov_diff
+        ,ROUND(r.c1_rov / NULLIF(ctrl.ctrl_c1_rov, 0) - 1, 6) AS c1_rov_diff
+        ,ROUND(r.cn_rov / NULLIF(ctrl.ctrl_cn_rov, 0) - 1, 6) AS cn_rov_diff
+        ,ROUND(r.d1_rov / NULLIF(ctrl.ctrl_d1_rov, 0) - 1, 6) AS d1_rov_diff
+        ,ROUND(r.dn_rov / NULLIF(ctrl.ctrl_dn_rov, 0) - 1, 6) AS dn_rov_diff
+        ,ROUND(r.total_rov / NULLIF(ctrl.ctrl_total_rov, 0) - 1, 6) AS total_rov_diff
+        ,ROUND(r.ecs / NULLIF(ctrl.ctrl_ecs, 0) - 1, 6) AS ecs_diff
+        ,ROUND(r.ecs_ratio / NULLIF(ctrl.ctrl_ecs_ratio, 0) - 1, 6) AS ecs_ratio_diff
+        ,ROUND(r.arp / NULLIF(ctrl.ctrl_arp, 0) - 1, 6) AS arp_diff
+FROM    t_combined r
+LEFT JOIN t_ctrl ctrl
+ON      r.dt = ctrl.dt
+AND     r.apptype = ctrl.apptype
+AND     r.suffix_pos = ctrl.suffix_pos
+ORDER BY r.dt DESC, r.suffix_pos, r.apptype, r.abcode, r.suffix_group
+;

+ 115 - 0
tasks/00_尾号实验/compute_base5_dau_24h.sql

@@ -0,0 +1,115 @@
+-- 一次性 SQL:计算 20260307~20260311 五天的 dau / dau_24h_in / dau_24h_out 基线均值
+-- 输出格式直接复制粘贴到 base_all_new_v3_分层_24h.sql 的 t_dau2_base5 CTE 里
+--
+-- 24h 定义(跟主 SQL 保持一致):
+--   24h内 = (clientTs - shareTs) ≤ 24h  OR 无可解析 shareId 时间戳(主动/投放首层)
+--   24h外 = (clientTs - shareTs) > 24h
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+,t_src AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,clienttimestamp
+            ,params
+            ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                    LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')), 1) AS suffix
+            ,subsessionid
+            ,sessionid
+            ,GET_JSON_OBJECT(extparams,'$.rootSessionId')                AS rsid
+            ,GET_JSON_OBJECT(extparams,'$.rootSourceId')                 AS rscid
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)       AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt BETWEEN '20260307' AND '20260311'
+    AND     apptype IN ("0","4")
+    AND     (apptype = "4"
+             OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+    AND     (apptype = "4"
+             OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+)
+,t_labeled AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,suffix
+            ,CASE WHEN rscid != '' AND rscid IS NOT NULL THEN '外部' ELSE '内部' END AS source_type
+            ,CASE WHEN rsid = subsessionid OR rsid = sessionid THEN '首层' ELSE '裂变层' END AS layer_type
+            ,CASE
+                WHEN params LIKE '%shareId=%'
+                 AND SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                       RLIKE '^[0-9]{13}$'
+                 AND (CAST(clienttimestamp AS BIGINT)
+                    - CAST(SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                           AS BIGINT)) > 86400000
+                    THEN '24h外'
+                ELSE '24h内'
+             END AS share_age
+    FROM t_src
+)
+-- ① 单日 × (apptype, suffix, source_type, layer_type) DAU — 按物理尾号 distinct
+,t_per_suffix AS
+(
+    SELECT  l.dt
+            ,l.apptype
+            ,sg.suffix_group
+            ,l.suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体')  AS layer_type
+            ,COUNT(DISTINCT machinecode)  AS dau2
+            ,COUNT(DISTINCT CASE WHEN share_age = '24h内' THEN machinecode END) AS dau_24h_in
+            ,COUNT(DISTINCT CASE WHEN share_age = '24h外' THEN machinecode END) AS dau_24h_out
+    FROM    t_labeled l
+    INNER JOIN t_suffix_group sg
+    ON      l.suffix = sg.suffix
+    GROUP BY l.dt, l.apptype, sg.suffix_group, l.suffix, source_type, layer_type
+    GROUPING SETS (
+        (l.dt, l.apptype, sg.suffix_group, l.suffix, source_type, layer_type),
+        (l.dt, l.apptype, sg.suffix_group, l.suffix)
+    )
+)
+-- ② 单日 × (apptype, suffix_group, source_type, layer_type) — 按 suffix 取平均
+,t_daily AS
+(
+    SELECT  dt
+            ,apptype
+            ,suffix_group
+            ,source_type
+            ,layer_type
+            ,AVG(dau2)        AS dau2
+            ,AVG(dau_24h_in)  AS dau_24h_in
+            ,AVG(dau_24h_out) AS dau_24h_out
+    FROM t_per_suffix
+    GROUP BY dt, apptype, suffix_group, source_type, layer_type
+)
+-- ③ 5 天均值
+SELECT
+    apptype
+    ,suffix_group
+    ,source_type
+    ,layer_type
+    ,ROUND(AVG(dau2),         1) AS dau2_base5
+    ,ROUND(AVG(dau_24h_in),   1) AS dau_24h_in_base5
+    ,ROUND(AVG(dau_24h_out),  1) AS dau_24h_out_base5
+    ,COUNT(*)                    AS days_observed
+FROM t_daily
+GROUP BY apptype, suffix_group, source_type, layer_type
+ORDER BY apptype, suffix_group, source_type, layer_type

+ 112 - 0
tasks/00_尾号实验/compute_base5_dau_today.sql

@@ -0,0 +1,112 @@
+-- 一次性 SQL:计算 20260307~20260311 五天的 dau / dau_today / dau_non_today 基线均值
+-- 输出格式直接复制粘贴到 base_all_new_v3_分层_当天.sql 的 t_dau2_base5 CTE 里
+--
+-- 当天/非当天定义(按自然日切,北京时间):
+--   非当天 = shareId 有 13 位时间戳 且 ts 日期 < dt 自然日
+--   当天   = 所有其他情况(同自然日 / 主动 / 投放首层 / shareId 异常)
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+,t_src AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,clienttimestamp
+            ,params
+            ,SUBSTR(GET_JSON_OBJECT(extparams,'$.rootSessionId'),
+                    LENGTH(GET_JSON_OBJECT(extparams,'$.rootSessionId')), 1) AS suffix
+            ,subsessionid
+            ,sessionid
+            ,GET_JSON_OBJECT(extparams,'$.rootSessionId')                AS rsid
+            ,GET_JSON_OBJECT(extparams,'$.rootSourceId')                 AS rscid
+            ,SPLIT_PART(SPLIT_PART(params, 'shareId=', 2), '&', 1)       AS share_id
+    FROM    loghubods.useractive_log
+    WHERE   dt BETWEEN '20260307' AND '20260311'
+    AND     apptype IN ("0","4")
+    AND     (apptype = "4"
+             OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') IN ("ab0","ab1","ab2","ab3","ab4","ab5","ab6","ab7","ab8","ab9"))
+    AND     (apptype = "4"
+             OR GET_JSON_OBJECT(extparams,'$.eventInfos.ab_test003') NOT IN ("ab100"))
+)
+,t_labeled AS
+(
+    SELECT  dt
+            ,apptype
+            ,machinecode
+            ,suffix
+            ,CASE WHEN rscid != '' AND rscid IS NOT NULL THEN '外部' ELSE '内部' END AS source_type
+            ,CASE WHEN rsid = subsessionid OR rsid = sessionid THEN '首层' ELSE '裂变层' END AS layer_type
+            ,CASE
+                -- 有可解析 shareId 时间戳 且 自然日不同
+                WHEN params LIKE '%shareId=%'
+                 AND SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                       RLIKE '^[0-9]{13}$'
+                 AND CAST((CAST(clienttimestamp AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                   > CAST((CAST(SUBSTR(share_id, LENGTH(share_id) - INSTR(REVERSE(share_id),'-') + 2)
+                              AS BIGINT) + 28800000) / 86400000 AS BIGINT)
+                    THEN '非当天'
+                ELSE '当天'
+             END AS share_age
+    FROM t_src
+)
+-- ① 单日 × (apptype, suffix, source_type, layer_type) DAU — 按物理尾号 distinct
+,t_per_suffix AS
+(
+    SELECT  l.dt
+            ,l.apptype
+            ,sg.suffix_group
+            ,l.suffix
+            ,COALESCE(source_type,'总体') AS source_type
+            ,COALESCE(layer_type,'总体')  AS layer_type
+            ,COUNT(DISTINCT machinecode)  AS dau2
+            ,COUNT(DISTINCT CASE WHEN share_age = '当天'   THEN machinecode END) AS dau_today
+            ,COUNT(DISTINCT CASE WHEN share_age = '非当天' THEN machinecode END) AS dau_non_today
+    FROM    t_labeled l
+    INNER JOIN t_suffix_group sg
+    ON      l.suffix = sg.suffix
+    GROUP BY l.dt, l.apptype, sg.suffix_group, l.suffix, source_type, layer_type
+    GROUPING SETS (
+        (l.dt, l.apptype, sg.suffix_group, l.suffix, source_type, layer_type),
+        (l.dt, l.apptype, sg.suffix_group, l.suffix)
+    )
+)
+-- ② 单日 × suffix_group — 按 suffix 取平均
+,t_daily AS
+(
+    SELECT  dt, apptype, suffix_group, source_type, layer_type
+            ,AVG(dau2)          AS dau2
+            ,AVG(dau_today)     AS dau_today
+            ,AVG(dau_non_today) AS dau_non_today
+    FROM t_per_suffix
+    GROUP BY dt, apptype, suffix_group, source_type, layer_type
+)
+-- ③ 5 天均值
+SELECT
+    apptype
+    ,suffix_group
+    ,source_type
+    ,layer_type
+    ,ROUND(AVG(dau2),          1) AS dau2_base5
+    ,ROUND(AVG(dau_today),     1) AS dau_today_base5
+    ,ROUND(AVG(dau_non_today), 1) AS dau_non_today_base5
+    ,COUNT(*)                     AS days_observed
+FROM t_daily
+GROUP BY apptype, suffix_group, source_type, layer_type
+ORDER BY apptype, suffix_group, source_type, layer_type

+ 647 - 0
tasks/tmp/tmp.sql

@@ -0,0 +1,647 @@
+set odps.sql.select.output.showcolumntype=true;
+WITH 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 = '20260517'
+    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
+)
+,t_base AS
+(
+    SELECT  dt
+            ,CASE   WHEN apptype IN ("0") THEN "0"
+                    WHEN apptype IN ("4") THEN "4"
+                    ELSE "其他"
+            END AS apptype
+            ,page_type
+            ,page
+            ,mid
+            ,vid
+            ,share_cnt
+            ,is_return_noself
+            ,return_n_uv
+            ,return_n_uv_noself
+            ,CAST(GET_JSON_OBJECT(scoresmap,'$.fmRov') AS DOUBLE) AS a_str_pred
+            ,1.22 * pow(CAST(GET_JSON_OBJECT(scoresmap,'$.NorXGBScore') AS DOUBLE), 1.15) AS bn_ros_pred
+            ,GET_JSON_OBJECT(v1_feature,'$.title') AS vid_title
+            
+            ,CAST(GET_JSON_OBJECT(extend_alg,'$.sortScore') AS DOUBLE) AS sortScore
+            ,CAST(GET_JSON_OBJECT(extend_alg,'$.rovScore') AS DOUBLE) AS rovScore
+            ,GET_JSON_OBJECT(extend_alg,'$.pushFrom') AS pushFrom
+            
+            ,CAST(GET_JSON_OBJECT(extend_alg,'$.scoreRos') AS DOUBLE) AS scoreRos
+            ,CAST(GET_JSON_OBJECT(extend_alg,'$.scoreStr') AS DOUBLE) AS scoreStr
+            ,CAST(GET_JSON_OBJECT(extend_alg,'$.pushfromrank') AS BIGINT) AS pushfromrank
+            
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.exp_168h') AS DOUBLE) AS b1_exp_168h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.return_1_uv_1h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b1_feature,'$.exp_1h') AS DOUBLE), 0) AS b1_rovn_1h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.return_1_uv_24h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b1_feature,'$.exp_24h') AS DOUBLE), 0) AS b1_rovn_24h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.rovn_168h') AS DOUBLE) AS b1_rovn_168h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.is_share_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b1_feature,'$.exp_168h') AS DOUBLE), 0) AS b1_str_168h
+            
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.return_1_uv_72h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b1_feature,'$.exp_72h') AS DOUBLE), 0) AS b1_rovn_72h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.is_share_24h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b1_feature,'$.exp_24h') AS DOUBLE), 0) AS b1_str_24h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.str_one_1h') AS DOUBLE) AS b1_str_one_1h
+            ,CAST(GET_JSON_OBJECT(b1_feature,'$.share_cnt_168h') AS DOUBLE) AS b1_share_cnt_168h
+            
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.return_n_uv_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b2_feature,'$.exp_168h') AS DOUBLE), 0) AS b2_rovn_168h
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.exp_168h') AS DOUBLE) AS b2_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.return_n_uv_1h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b2_feature,'$.exp_1h') AS DOUBLE), 0) AS b2_rovn_1h
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.return_n_uv_24h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b2_feature,'$.exp_24h') AS DOUBLE), 0) AS b2_rovn_24h
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.is_share_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b2_feature,'$.exp_168h') AS DOUBLE), 0) AS b2_str_168h
+            ,CAST(GET_JSON_OBJECT(b2_feature,'$.new_exposure_cnt_168h') AS DOUBLE) AS b2_new_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(b3_feature,'$.return_n_uv_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b3_feature,'$.exp_168h') AS DOUBLE), 0) AS b3_rovn_168h
+            ,CAST(GET_JSON_OBJECT(b3_feature,'$.exp_168h') AS DOUBLE) AS b3_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.return_n_uv_30d') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b12_feature,'$.exp_30d') AS DOUBLE), 0) AS b12_rovn_30d
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.exp_30d') AS DOUBLE) AS b12_exp_30d
+            
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.return_n_uv_7d') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b12_feature,'$.exp_7d') AS DOUBLE), 0) AS b12_rovn_7d
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.return_n_uv_60d') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b12_feature,'$.exp_60d') AS DOUBLE), 0) AS b12_rovn_60d
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.is_share_30d') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b12_feature,'$.exp_30d') AS DOUBLE), 0) AS b12_str_30d
+            ,CAST(GET_JSON_OBJECT(b12_feature,'$.exp_60d') AS DOUBLE) AS b12_exp_60d
+            
+            ,CAST(GET_JSON_OBJECT(c1_feature,'$.rovn_168h') AS DOUBLE) AS c1_rovn_168h
+            ,CAST(GET_JSON_OBJECT(c1_feature,'$.exp_168h') AS DOUBLE) AS c1_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(c1_feature,'$.is_share_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(c1_feature,'$.exp_168h') AS DOUBLE), 0) AS c1_str_168h
+            ,CAST(GET_JSON_OBJECT(c1_feature,'$.return_1_uv_24h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(c1_feature,'$.exp_24h') AS DOUBLE), 0) AS c1_rovn_24h
+            ,CAST(GET_JSON_OBJECT(c1_feature,'$.click_168h') AS DOUBLE) AS c1_click_168h
+            
+            ,CAST(GET_JSON_OBJECT(b8_feature,'$.return_n_uv_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b8_feature,'$.exp_168h') AS DOUBLE), 0) AS b8_rovn_168h
+            
+            ,CAST(GET_JSON_OBJECT(b8_feature,'$.exp_168h') AS DOUBLE) AS b8_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(b9_feature,'$.return_n_uv_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b9_feature,'$.exp_168h') AS DOUBLE), 0) AS b9_rovn_168h
+            ,CAST(GET_JSON_OBJECT(b9_feature,'$.exp_168h') AS DOUBLE) AS b9_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(b10_feature,'$.return_n_uv_168h') AS DOUBLE)
+                / NULLIF(CAST(GET_JSON_OBJECT(b10_feature,'$.exp_168h') AS DOUBLE), 0) AS b10_rovn_168h
+            ,CAST(GET_JSON_OBJECT(b10_feature,'$.exp_168h') AS DOUBLE) AS b10_exp_168h
+            
+            ,CAST(GET_JSON_OBJECT(d3_feature,'$.rovn') AS DOUBLE) AS d3_rovn
+            ,CAST(GET_JSON_OBJECT(d3_feature,'$.exp') AS DOUBLE) AS d3_exp
+            
+            ,GET_JSON_OBJECT(v1_feature,'$.channel') AS channel
+            ,GET_JSON_OBJECT(v1_feature,'$.merge_first_level_cate') AS merge_cate1
+            ,CAST(GET_JSON_OBJECT(v1_feature,'$.total_time') AS DOUBLE) AS total_time
+            
+            ,GET_JSON_OBJECT(v1_feature,'$.merge_second_level_cate') AS merge_cate2
+            ,GET_JSON_OBJECT(v1_feature,'$.vid_source') AS vid_source
+            ,GET_JSON_OBJECT(v1_feature,'$.is_fes') AS is_fes
+            ,GET_JSON_OBJECT(v1_feature,'$.attribute_province') AS attribute_province
+            
+            ,CAST(GET_JSON_OBJECT(extend, '$.extParams.sequence') AS BIGINT) AS seq_position
+    FROM    t_raw
+)
+,t_valid AS
+(
+    SELECT  *
+    FROM    t_base
+    WHERE   a_str_pred IS NOT NULL
+    AND     bn_ros_pred IS NOT NULL
+)
+,t_pushfrom_ranked AS
+(
+    SELECT  dt
+            ,COALESCE(apptype, 'all') AS apptype
+            ,COALESCE(page_type, 'all') AS page_type
+            ,COALESCE(page, 'all') AS page
+            ,vid
+            ,pushFrom
+            ,COUNT(1) AS pf_cnt
+            ,ROW_NUMBER() OVER (
+                PARTITION BY dt, COALESCE(apptype,'all'), COALESCE(page_type,'all'), COALESCE(page,'all'), vid
+                ORDER BY COUNT(1) DESC
+            ) AS pf_rank
+    FROM    t_valid
+    GROUP BY dt, apptype, page_type, page, vid, pushFrom
+    GROUPING SETS (
+        (dt, apptype, page_type, page, vid, pushFrom),
+        (dt, apptype, page_type, vid, pushFrom),
+        (dt, apptype, page, vid, pushFrom),
+        (dt, page_type, page, vid, pushFrom),
+        (dt, apptype, vid, pushFrom),
+        (dt, page_type, vid, pushFrom),
+        (dt, page, vid, pushFrom),
+        (dt, vid, pushFrom)
+    )
+)
+,t_pushfrom_mode AS
+(
+    SELECT  dt, apptype, page_type, page, vid, pushFrom AS top_pushFrom
+    FROM    t_pushfrom_ranked
+    WHERE   pf_rank = 1
+)
+,t_vid_agg_base AS
+(
+    SELECT  dt
+            ,COALESCE(apptype, 'all') AS apptype
+            ,COALESCE(page_type, 'all') AS page_type
+            ,COALESCE(page, 'all') AS page
+            ,vid
+            ,MAX(vid_title) AS vid_title
+            
+            ,COUNT(1) AS exp_cnt
+            ,COALESCE(SUM(share_cnt),0) AS share_cnt
+            ,COALESCE(SUM(return_n_uv),0) AS return_cnt
+            
+            ,SUM(is_return_noself) AS is_return_noself_cnt
+            ,SUM(return_n_uv_noself) AS return_noself_sum
+            ,SUM(a_str_pred) AS a_strx_pred_sum
+            ,SUM(CASE WHEN is_return_noself = 1 THEN bn_ros_pred END) AS bn_rosx_pred_wsum
+            ,SUM(CASE WHEN is_return_noself = 1 THEN 1 END) AS bn_rosx_pred_cnt
+            ,SUM(a_str_pred * bn_ros_pred) AS bn_rovx_pred_sum
+            
+            ,round(COALESCE(SUM(share_cnt) / COUNT(1),0),6) AS a_str
+            ,round(COALESCE(SUM(return_n_uv) / SUM(share_cnt),0),6) AS bn_ros
+            ,round(COALESCE(SUM(return_n_uv) / COUNT(1),0),6) AS bn_rov
+            
+            ,round(COALESCE(SUM(is_return_noself) / COUNT(1),0),6) AS a_strx
+            ,round(COALESCE(SUM(return_n_uv_noself) / NULLIF(SUM(is_return_noself),0),0),6) AS bn_rosx
+            ,round(COALESCE(SUM(return_n_uv_noself) / COUNT(1),0),6) AS bn_rovx
+            
+            ,round(AVG(a_str_pred),6) AS a_strx_pred
+            ,round(AVG(CASE WHEN is_return_noself = 1 THEN bn_ros_pred END),6) AS bn_rosx_pred
+            ,round(AVG(a_str_pred * bn_ros_pred),6) AS bn_rovx_pred
+            
+            ,round((SUM(is_return_noself) / COUNT(1)) / NULLIF(SUM(a_str_pred) / COUNT(1), 0), 4) AS a_strx_copc
+            ,round(AVG(CASE WHEN is_return_noself = 1 THEN return_n_uv_noself END) / NULLIF(AVG(CASE WHEN is_return_noself = 1 THEN bn_ros_pred END), 0), 4) AS bn_rosx_copc
+            ,round((SUM(return_n_uv_noself) / COUNT(1)) / NULLIF(AVG(a_str_pred * bn_ros_pred), 0), 4) AS bn_rovx_copc
+            
+            ,round(AVG(sortScore),4) AS avg_sortScore
+            ,round(AVG(rovScore),4) AS avg_rovScore
+            ,SUM(sortScore) AS sortScore_sum
+            ,SUM(rovScore) AS rovScore_sum
+            
+            ,round(AVG(scoreRos),4) AS avg_scoreRos
+            ,SUM(scoreRos) AS scoreRos_sum
+            ,round(AVG(scoreStr),4) AS avg_scoreStr
+            ,SUM(scoreStr) AS scoreStr_sum
+            ,round(AVG(pushfromrank),1) AS avg_pushfromrank
+            ,SUM(pushfromrank) AS pushfromrank_sum
+            
+            ,round(AVG(b1_exp_168h),0) AS b1_exp_168h
+            ,SUM(b1_exp_168h) AS b1_exp_168h_sum
+            ,round(AVG(b1_rovn_1h),6) AS b1_rovn_1h
+            ,SUM(b1_rovn_1h) AS b1_rovn_1h_sum
+            ,round(AVG(b1_rovn_24h),6) AS b1_rovn_24h
+            ,SUM(b1_rovn_24h) AS b1_rovn_24h_sum
+            ,round(AVG(b1_rovn_168h),6) AS b1_rovn_168h
+            ,SUM(b1_rovn_168h) AS b1_rovn_168h_sum
+            ,round(AVG(b1_str_168h),6) AS b1_str_168h
+            ,SUM(b1_str_168h) AS b1_str_168h_sum
+            
+            ,round(AVG(b1_rovn_72h),6) AS b1_rovn_72h
+            ,SUM(b1_rovn_72h) AS b1_rovn_72h_sum
+            ,round(AVG(b1_str_24h),6) AS b1_str_24h
+            ,SUM(b1_str_24h) AS b1_str_24h_sum
+            ,round(AVG(b1_str_one_1h),6) AS b1_str_one_1h
+            ,SUM(b1_str_one_1h) AS b1_str_one_1h_sum
+            ,round(AVG(b1_share_cnt_168h),0) AS b1_share_cnt_168h
+            ,SUM(b1_share_cnt_168h) AS b1_share_cnt_168h_sum
+            
+            ,round(AVG(b2_rovn_168h),6) AS b2_rovn_168h
+            ,SUM(b2_rovn_168h) AS b2_rovn_168h_sum
+            ,round(AVG(b2_exp_168h),0) AS b2_exp_168h
+            ,SUM(b2_exp_168h) AS b2_exp_168h_sum
+            
+            ,round(AVG(b2_rovn_1h),6) AS b2_rovn_1h
+            ,SUM(b2_rovn_1h) AS b2_rovn_1h_sum
+            ,round(AVG(b2_rovn_24h),6) AS b2_rovn_24h
+            ,SUM(b2_rovn_24h) AS b2_rovn_24h_sum
+            ,round(AVG(b2_str_168h),6) AS b2_str_168h
+            ,SUM(b2_str_168h) AS b2_str_168h_sum
+            ,round(AVG(b2_new_exp_168h),0) AS b2_new_exp_168h
+            ,SUM(b2_new_exp_168h) AS b2_new_exp_168h_sum
+            
+            ,round(AVG(b3_rovn_168h),6) AS b3_rovn_168h
+            ,SUM(b3_rovn_168h) AS b3_rovn_168h_sum
+            ,round(AVG(b3_exp_168h),0) AS b3_exp_168h
+            ,SUM(b3_exp_168h) AS b3_exp_168h_sum
+            
+            ,round(AVG(b12_rovn_30d),6) AS b12_rovn_30d
+            ,SUM(b12_rovn_30d) AS b12_rovn_30d_sum
+            ,round(AVG(b12_exp_30d),0) AS b12_exp_30d
+            ,SUM(b12_exp_30d) AS b12_exp_30d_sum
+            
+            ,round(AVG(b12_rovn_7d),6) AS b12_rovn_7d
+            ,SUM(b12_rovn_7d) AS b12_rovn_7d_sum
+            ,round(AVG(b12_rovn_60d),6) AS b12_rovn_60d
+            ,SUM(b12_rovn_60d) AS b12_rovn_60d_sum
+            ,round(AVG(b12_str_30d),6) AS b12_str_30d
+            ,SUM(b12_str_30d) AS b12_str_30d_sum
+            ,round(AVG(b12_exp_60d),0) AS b12_exp_60d
+            ,SUM(b12_exp_60d) AS b12_exp_60d_sum
+            
+            ,round(AVG(c1_rovn_168h),6) AS avg_c1_rovn_168h
+            ,SUM(c1_rovn_168h) AS c1_rovn_168h_sum
+            ,round(AVG(c1_exp_168h),0) AS avg_c1_exp_168h
+            ,SUM(c1_exp_168h) AS c1_exp_168h_sum
+            
+            ,round(AVG(c1_str_168h),6) AS avg_c1_str_168h
+            ,SUM(c1_str_168h) AS c1_str_168h_sum
+            ,round(AVG(c1_rovn_24h),6) AS avg_c1_rovn_24h
+            ,SUM(c1_rovn_24h) AS c1_rovn_24h_sum
+            ,round(AVG(c1_click_168h),0) AS avg_c1_click_168h
+            ,SUM(c1_click_168h) AS c1_click_168h_sum
+            
+            ,round(AVG(b8_rovn_168h),6) AS b8_rovn_168h
+            ,SUM(b8_rovn_168h) AS b8_rovn_168h_sum
+            
+            ,round(AVG(b8_exp_168h),0) AS b8_exp_168h
+            ,SUM(b8_exp_168h) AS b8_exp_168h_sum
+            
+            ,round(AVG(b9_rovn_168h),6) AS b9_rovn_168h
+            ,SUM(b9_rovn_168h) AS b9_rovn_168h_sum
+            ,round(AVG(b9_exp_168h),0) AS b9_exp_168h
+            ,SUM(b9_exp_168h) AS b9_exp_168h_sum
+            
+            ,round(AVG(b10_rovn_168h),6) AS b10_rovn_168h
+            ,SUM(b10_rovn_168h) AS b10_rovn_168h_sum
+            ,round(AVG(b10_exp_168h),0) AS b10_exp_168h
+            ,SUM(b10_exp_168h) AS b10_exp_168h_sum
+            
+            ,round(AVG(d3_rovn),6) AS d3_rovn
+            ,SUM(d3_rovn) AS d3_rovn_sum
+            ,round(AVG(d3_exp),0) AS d3_exp
+            ,SUM(d3_exp) AS d3_exp_sum
+            
+            ,MAX(channel) AS channel
+            ,MAX(merge_cate1) AS merge_cate1
+            ,round(AVG(total_time),0) AS total_time
+            ,SUM(total_time) AS total_time_sum
+            
+            ,MAX(merge_cate2) AS merge_cate2
+            ,MAX(vid_source) AS vid_source
+            ,MAX(is_fes) AS is_fes
+            ,MAX(attribute_province) AS attribute_province
+            
+            ,round(AVG(seq_position),1) AS avg_seq_position
+            ,SUM(seq_position) AS seq_position_sum
+    FROM    t_valid
+    GROUP BY dt, apptype, page_type, page, vid
+    GROUPING SETS (
+        (dt, apptype, page_type, page, vid),
+        (dt, apptype, page_type, vid),
+        (dt, apptype, page, vid),
+        (dt, page_type, page, vid),
+        (dt, apptype, vid),
+        (dt, page_type, vid),
+        (dt, page, vid),
+        (dt, vid)
+    )
+)
+,t_vid_agg AS
+(
+    SELECT  a.*
+            ,b.top_pushFrom
+    FROM    t_vid_agg_base a
+    LEFT JOIN t_pushfrom_mode b
+    ON      a.dt = b.dt
+    AND     a.apptype = b.apptype
+    AND     a.page_type = b.page_type
+    AND     a.page = b.page
+    AND     a.vid = b.vid
+)
+,t_ranked AS
+(
+    SELECT  *
+            ,ROW_NUMBER() OVER (PARTITION BY dt, apptype, page_type, page ORDER BY exp_cnt DESC) AS exp_rank
+    FROM    t_vid_agg
+)
+,t_top20 AS
+(
+    SELECT  *
+            ,ROW_NUMBER() OVER (PARTITION BY dt, apptype, page_type, page ORDER BY bn_rov DESC) AS bn_rovn_rank
+            ,ROW_NUMBER() OVER (PARTITION BY dt, apptype, page_type, page ORDER BY avg_seq_position ASC) AS seq_rank
+            ,ROW_NUMBER() OVER (PARTITION BY dt, apptype, page_type, page ORDER BY avg_sortScore DESC) AS score_rank
+    FROM    t_ranked
+    WHERE   exp_rank <= 20
+)
+,t_other_summary AS
+(
+    SELECT  dt, apptype, page_type, page
+            ,'其他' AS vid
+            ,CAST(NULL AS STRING) AS vid_title
+            ,CAST(NULL AS BIGINT) AS exp_rank
+            ,CAST(NULL AS BIGINT) AS bn_rovn_rank
+            ,CAST(NULL AS BIGINT) AS seq_rank
+            ,CAST(NULL AS BIGINT) AS score_rank
+            
+            ,SUM(exp_cnt) AS exp_cnt
+            ,SUM(share_cnt) AS share_cnt
+            ,SUM(return_cnt) AS return_cnt
+            
+            ,round(SUM(share_cnt) * 1.0 / NULLIF(SUM(exp_cnt), 0), 6) AS a_str
+            ,round(SUM(return_cnt) * 1.0 / NULLIF(SUM(share_cnt), 0), 6) AS bn_ros
+            ,round(SUM(return_cnt) * 1.0 / NULLIF(SUM(exp_cnt), 0), 6) AS bn_rov
+            
+            ,round(SUM(is_return_noself_cnt) * 1.0 / NULLIF(SUM(exp_cnt), 0), 6) AS a_strx
+            ,round(SUM(return_noself_sum) * 1.0 / NULLIF(SUM(is_return_noself_cnt), 0), 6) AS bn_rosx
+            ,round(SUM(return_noself_sum) * 1.0 / NULLIF(SUM(exp_cnt), 0), 6) AS bn_rovx
+            
+            ,round(SUM(a_strx_pred_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS a_strx_pred
+            ,round(SUM(bn_rosx_pred_wsum) / NULLIF(SUM(bn_rosx_pred_cnt), 0), 6) AS bn_rosx_pred
+            ,round(SUM(bn_rovx_pred_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS bn_rovx_pred
+            
+            ,round(SUM(is_return_noself_cnt) * 1.0 / NULLIF(SUM(a_strx_pred_sum), 0), 4) AS a_strx_copc
+            ,round((SUM(return_noself_sum) * 1.0 / NULLIF(SUM(is_return_noself_cnt), 0)) / NULLIF(SUM(bn_rosx_pred_wsum) / NULLIF(SUM(bn_rosx_pred_cnt), 0), 0), 4) AS bn_rosx_copc
+            ,round(SUM(return_noself_sum) * 1.0 / NULLIF(SUM(bn_rovx_pred_sum), 0), 4) AS bn_rovx_copc
+            
+            ,round(SUM(sortScore_sum) / NULLIF(SUM(exp_cnt), 0), 4) AS avg_sortScore
+            ,round(SUM(rovScore_sum) / NULLIF(SUM(exp_cnt), 0), 4) AS avg_rovScore
+            ,CAST(NULL AS STRING) AS top_pushFrom
+            ,round(SUM(seq_position_sum) / NULLIF(SUM(exp_cnt), 0), 1) AS avg_seq_position
+            
+            ,round(SUM(scoreRos_sum) / NULLIF(SUM(exp_cnt), 0), 4) AS avg_scoreRos
+            ,round(SUM(scoreStr_sum) / NULLIF(SUM(exp_cnt), 0), 4) AS avg_scoreStr
+            ,round(SUM(pushfromrank_sum) / NULLIF(SUM(exp_cnt), 0), 1) AS avg_pushfromrank
+            
+            ,round(SUM(b1_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b1_exp_168h
+            ,round(SUM(b1_rovn_1h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_rovn_1h
+            ,round(SUM(b1_rovn_24h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_rovn_24h
+            ,round(SUM(b1_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_rovn_168h
+            ,round(SUM(b1_str_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_str_168h
+            
+            ,round(SUM(b1_rovn_72h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_rovn_72h
+            ,round(SUM(b1_str_24h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_str_24h
+            ,round(SUM(b1_str_one_1h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b1_str_one_1h
+            ,round(SUM(b1_share_cnt_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b1_share_cnt_168h
+            ,round(SUM(b2_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b2_rovn_168h
+            ,round(SUM(b2_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b2_exp_168h
+            
+            ,round(SUM(b2_rovn_1h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b2_rovn_1h
+            ,round(SUM(b2_rovn_24h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b2_rovn_24h
+            ,round(SUM(b2_str_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b2_str_168h
+            ,round(SUM(b2_new_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b2_new_exp_168h
+            
+            ,round(SUM(b3_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b3_rovn_168h
+            ,round(SUM(b3_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b3_exp_168h
+            ,round(SUM(b12_rovn_30d_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b12_rovn_30d
+            ,round(SUM(b12_exp_30d_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b12_exp_30d
+            
+            ,round(SUM(b12_rovn_7d_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b12_rovn_7d
+            ,round(SUM(b12_rovn_60d_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b12_rovn_60d
+            ,round(SUM(b12_str_30d_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b12_str_30d
+            ,round(SUM(b12_exp_60d_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b12_exp_60d
+            
+            ,round(SUM(c1_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS avg_c1_rovn_168h
+            ,round(SUM(c1_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS avg_c1_exp_168h
+            
+            ,round(SUM(c1_str_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS avg_c1_str_168h
+            ,round(SUM(c1_rovn_24h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS avg_c1_rovn_24h
+            ,round(SUM(c1_click_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS avg_c1_click_168h
+            
+            ,round(SUM(b8_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b8_rovn_168h
+            
+            ,round(SUM(b8_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b8_exp_168h
+            
+            ,round(SUM(b9_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b9_rovn_168h
+            ,round(SUM(b9_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b9_exp_168h
+            
+            ,round(SUM(b10_rovn_168h_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS b10_rovn_168h
+            ,round(SUM(b10_exp_168h_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS b10_exp_168h
+            
+            ,round(SUM(d3_rovn_sum) / NULLIF(SUM(exp_cnt), 0), 6) AS d3_rovn
+            ,round(SUM(d3_exp_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS d3_exp
+            ,CAST(NULL AS STRING) AS channel
+            ,CAST(NULL AS STRING) AS merge_cate1
+            ,round(SUM(total_time_sum) / NULLIF(SUM(exp_cnt), 0), 0) AS total_time
+            
+            ,CAST(NULL AS STRING) AS merge_cate2
+            ,CAST(NULL AS STRING) AS vid_source
+            ,CAST(NULL AS STRING) AS is_fes
+            ,CAST(NULL AS STRING) AS attribute_province
+    FROM    t_ranked
+    WHERE   exp_rank > 20
+    GROUP BY dt, apptype, page_type, page
+)
+,t_all_summary AS
+(
+    SELECT  dt
+            ,COALESCE(apptype, 'all') AS apptype
+            ,COALESCE(page_type, 'all') AS page_type
+            ,COALESCE(page, 'all') AS page
+            ,'all' AS vid
+            ,CAST(NULL AS STRING) AS vid_title
+            ,CAST(NULL AS BIGINT) AS exp_rank
+            ,CAST(NULL AS BIGINT) AS bn_rovn_rank
+            ,CAST(NULL AS BIGINT) AS seq_rank
+            ,CAST(NULL AS BIGINT) AS score_rank
+            
+            ,COUNT(1) AS exp_cnt
+            ,COALESCE(SUM(share_cnt),0) AS share_cnt
+            ,COALESCE(SUM(return_n_uv),0) AS return_cnt
+            
+            ,round(COALESCE(SUM(share_cnt) / COUNT(1),0),6) AS a_str
+            ,round(COALESCE(SUM(return_n_uv) / SUM(share_cnt),0),6) AS bn_ros
+            ,round(COALESCE(SUM(return_n_uv) / COUNT(1),0),6) AS bn_rov
+            
+            ,round(COALESCE(SUM(is_return_noself) / COUNT(1),0),6) AS a_strx
+            ,round(COALESCE(SUM(return_n_uv_noself) / NULLIF(SUM(is_return_noself),0),0),6) AS bn_rosx
+            ,round(COALESCE(SUM(return_n_uv_noself) / COUNT(1),0),6) AS bn_rovx
+            
+            ,round(AVG(a_str_pred),6) AS a_strx_pred
+            ,round(AVG(CASE WHEN is_return_noself = 1 THEN bn_ros_pred END),6) AS bn_rosx_pred
+            ,round(AVG(a_str_pred * bn_ros_pred),6) AS bn_rovx_pred
+            
+            ,round((SUM(is_return_noself) / COUNT(1)) / NULLIF(SUM(a_str_pred) / COUNT(1), 0), 4) AS a_strx_copc
+            ,round(AVG(CASE WHEN is_return_noself = 1 THEN return_n_uv_noself END) / NULLIF(AVG(CASE WHEN is_return_noself = 1 THEN bn_ros_pred END), 0), 4) AS bn_rosx_copc
+            ,round((SUM(return_n_uv_noself) / COUNT(1)) / NULLIF(AVG(a_str_pred * bn_ros_pred), 0), 4) AS bn_rovx_copc
+            
+            ,round(AVG(sortScore),4) AS avg_sortScore
+            ,round(AVG(rovScore),4) AS avg_rovScore
+            ,CAST(NULL AS STRING) AS top_pushFrom
+            ,round(AVG(seq_position),1) AS avg_seq_position
+            
+            ,round(AVG(scoreRos),4) AS avg_scoreRos
+            ,round(AVG(scoreStr),4) AS avg_scoreStr
+            ,round(AVG(pushfromrank),1) AS avg_pushfromrank
+            
+            ,round(AVG(b1_exp_168h),0) AS b1_exp_168h
+            ,round(AVG(b1_rovn_1h),6) AS b1_rovn_1h
+            ,round(AVG(b1_rovn_24h),6) AS b1_rovn_24h
+            ,round(AVG(b1_rovn_168h),6) AS b1_rovn_168h
+            ,round(AVG(b1_str_168h),6) AS b1_str_168h
+            
+            ,round(AVG(b1_rovn_72h),6) AS b1_rovn_72h
+            ,round(AVG(b1_str_24h),6) AS b1_str_24h
+            ,round(AVG(b1_str_one_1h),6) AS b1_str_one_1h
+            ,round(AVG(b1_share_cnt_168h),0) AS b1_share_cnt_168h
+            ,round(AVG(b2_rovn_168h),6) AS b2_rovn_168h
+            ,round(AVG(b2_exp_168h),0) AS b2_exp_168h
+            
+            ,round(AVG(b2_rovn_1h),6) AS b2_rovn_1h
+            ,round(AVG(b2_rovn_24h),6) AS b2_rovn_24h
+            ,round(AVG(b2_str_168h),6) AS b2_str_168h
+            ,round(AVG(b2_new_exp_168h),0) AS b2_new_exp_168h
+            
+            ,round(AVG(b3_rovn_168h),6) AS b3_rovn_168h
+            ,round(AVG(b3_exp_168h),0) AS b3_exp_168h
+            ,round(AVG(b12_rovn_30d),6) AS b12_rovn_30d
+            ,round(AVG(b12_exp_30d),0) AS b12_exp_30d
+            
+            ,round(AVG(b12_rovn_7d),6) AS b12_rovn_7d
+            ,round(AVG(b12_rovn_60d),6) AS b12_rovn_60d
+            ,round(AVG(b12_str_30d),6) AS b12_str_30d
+            ,round(AVG(b12_exp_60d),0) AS b12_exp_60d
+            
+            ,round(AVG(c1_rovn_168h),6) AS avg_c1_rovn_168h
+            ,round(AVG(c1_exp_168h),0) AS avg_c1_exp_168h
+            
+            ,round(AVG(c1_str_168h),6) AS avg_c1_str_168h
+            ,round(AVG(c1_rovn_24h),6) AS avg_c1_rovn_24h
+            ,round(AVG(c1_click_168h),0) AS avg_c1_click_168h
+            
+            ,round(AVG(b8_rovn_168h),6) AS b8_rovn_168h
+            
+            ,round(AVG(b8_exp_168h),0) AS b8_exp_168h
+            
+            ,round(AVG(b9_rovn_168h),6) AS b9_rovn_168h
+            ,round(AVG(b9_exp_168h),0) AS b9_exp_168h
+            
+            ,round(AVG(b10_rovn_168h),6) AS b10_rovn_168h
+            ,round(AVG(b10_exp_168h),0) AS b10_exp_168h
+            
+            ,round(AVG(d3_rovn),6) AS d3_rovn
+            ,round(AVG(d3_exp),0) AS d3_exp
+            ,CAST(NULL AS STRING) AS channel
+            ,CAST(NULL AS STRING) AS merge_cate1
+            ,round(AVG(total_time),0) AS total_time
+            
+            ,CAST(NULL AS STRING) AS merge_cate2
+            ,CAST(NULL AS STRING) AS vid_source
+            ,CAST(NULL AS STRING) AS is_fes
+            ,CAST(NULL AS STRING) AS attribute_province
+    FROM    t_valid
+    GROUP BY dt, apptype, page_type, page
+    GROUPING SETS (
+        (dt, apptype, page_type, page),
+        (dt, apptype, page_type),
+        (dt, apptype, page),
+        (dt, page_type, page),
+        (dt, apptype),
+        (dt, page_type),
+        (dt, page),
+        (dt)
+    )
+)
+SELECT  dt
+        ,apptype
+        ,page_type
+        ,page
+        ,vid
+        ,vid_title
+        ,exp_rank
+        ,bn_rovn_rank
+        ,seq_rank
+        ,score_rank
+        ,round(exp_cnt * 1.0 / MAX(CASE WHEN vid = 'all' THEN exp_cnt END) OVER (PARTITION BY dt, apptype, page_type, page), 4) AS exp_pct
+        ,exp_cnt, share_cnt, return_cnt
+        ,a_str, bn_ros, bn_rov
+        ,a_strx, bn_rosx, bn_rovx
+        ,a_strx_pred, bn_rosx_pred, bn_rovx_pred
+        ,a_strx_copc, bn_rosx_copc, bn_rovx_copc
+        ,avg_sortScore, avg_rovScore
+        ,top_pushFrom
+        ,avg_seq_position
+        
+        ,avg_scoreRos, avg_scoreStr, avg_pushfromrank
+        ,b1_exp_168h, b1_rovn_1h, b1_rovn_24h, b1_rovn_168h, b1_str_168h
+        
+        ,b1_rovn_72h, b1_str_24h, b1_str_one_1h, b1_share_cnt_168h
+        ,b2_rovn_168h, b2_exp_168h
+        
+        ,b2_rovn_1h, b2_rovn_24h, b2_str_168h, b2_new_exp_168h
+        
+        ,b3_rovn_168h, b3_exp_168h
+        ,b12_rovn_30d, b12_exp_30d
+        
+        ,b12_rovn_7d, b12_rovn_60d, b12_str_30d, b12_exp_60d
+        ,avg_c1_rovn_168h, avg_c1_exp_168h
+        
+        ,avg_c1_str_168h, avg_c1_rovn_24h, avg_c1_click_168h
+        ,b8_rovn_168h
+        
+        ,b8_exp_168h
+        
+        ,b9_rovn_168h, b9_exp_168h
+        
+        ,b10_rovn_168h, b10_exp_168h
+        
+        ,d3_rovn, d3_exp
+        ,channel, merge_cate1, total_time
+        
+        ,merge_cate2, vid_source, is_fes, attribute_province
+FROM    (
+        SELECT  dt,apptype,page_type,page,vid,vid_title,exp_rank,bn_rovn_rank,seq_rank,score_rank
+                ,exp_cnt,share_cnt,return_cnt
+                ,a_str,bn_ros,bn_rov,a_strx,bn_rosx,bn_rovx
+                ,a_strx_pred,bn_rosx_pred,bn_rovx_pred
+                ,a_strx_copc,bn_rosx_copc,bn_rovx_copc
+                ,avg_sortScore,avg_rovScore,top_pushFrom
+                ,avg_seq_position
+                
+                ,avg_scoreRos,avg_scoreStr,avg_pushfromrank
+                ,b1_exp_168h,b1_rovn_1h,b1_rovn_24h,b1_rovn_168h,b1_str_168h
+                
+                ,b1_rovn_72h,b1_str_24h,b1_str_one_1h,b1_share_cnt_168h
+                ,b2_rovn_168h,b2_exp_168h
+                
+                ,b2_rovn_1h,b2_rovn_24h,b2_str_168h,b2_new_exp_168h
+                
+                ,b3_rovn_168h,b3_exp_168h
+                ,b12_rovn_30d,b12_exp_30d
+                
+                ,b12_rovn_7d,b12_rovn_60d,b12_str_30d,b12_exp_60d
+                ,avg_c1_rovn_168h,avg_c1_exp_168h
+                
+                ,avg_c1_str_168h,avg_c1_rovn_24h,avg_c1_click_168h
+                ,b8_rovn_168h
+                
+                ,b8_exp_168h
+                
+                ,b9_rovn_168h,b9_exp_168h
+                
+                ,b10_rovn_168h,b10_exp_168h
+                
+                ,d3_rovn,d3_exp
+                ,channel,merge_cate1,total_time
+                
+                ,merge_cate2,vid_source,is_fes,attribute_province
+        FROM    t_top20
+        UNION ALL
+        SELECT  * FROM t_other_summary
+        UNION ALL
+        SELECT  * FROM t_all_summary
+        ) t
+ORDER BY dt DESC, apptype, page_type, page, exp_cnt DESC;

+ 364 - 0
tasks/召回策略效果/base_baseline_named_按桶_供给.sql

@@ -0,0 +1,364 @@
+-- 全量基线 · V566 实验"供给类型 × 驱动策略"效率分析
+-- 基于 base_baseline_named_按桶_独占.sql 改造:把"召回源"维度替换为"供给类型 + 驱动策略"
+--
+-- 数据源切换说明:
+--   ↪ 原: loghubods.dwd_recsys_alg_exposure_base_20250108(仅有 recommendlogvo.pushFromIndexList)
+--   ↪ 新: loghubods.dwd_recsys_alg_sample_all_20250212(多了 extend_alg.scoresMap,含 V566 注入的供给字段)
+--   ↪ sample 表分区为 (dt, hh) 双层 → 单天扫 24 小时分区,体量 ~24×,注意成本
+--
+-- 供给字段来源:V566 RankStrategy 把 supplyType / drivingStrategy / sceneDimension 写入 scoresMap:
+--   item.getScoresMap().put("supplyType_"     + supplyType,     1.0);
+--   item.getScoresMap().put("drivingStrategy_"+ drivingStrategy,1.0);
+--   item.getScoresMap().put("sceneDimension_" + sceneDimension, 1.0);
+--   item.getScoresMap().put("supplyTypeWeight", weight);  -- 实际打到分上的乘数
+-- 提取方式:REGEXP_EXTRACT(scoresmap,'"supplyType_([^"]+)"',1)
+--
+-- 范围说明:只有 V566 RankStrategy 写这些字段 → WHERE supply_type IS NOT NULL 自动收敛到 V566 桶
+--
+-- 输出层级(row_order):
+--   0 = (apptype, abcode, suffix_group) 总计
+--   1 = (apptype, abcode, suffix_group) × (供给类型, 驱动策略) 汇总
+--
+-- 跑批:python fetch_daily.py tasks/召回策略效果/base_baseline_named_按桶_供给.sql --days 7
+
+WITH t_suffix_group AS
+(
+    SELECT "a" AS suffix, "ab" AS suffix_group
+    UNION ALL SELECT "b", "ab"
+    UNION ALL SELECT "0", "01"
+    UNION ALL SELECT "1", "01"
+    UNION ALL SELECT "2", "2c"
+    UNION ALL SELECT "c", "2c"
+    UNION ALL SELECT "3", "34"
+    UNION ALL SELECT "4", "34"
+    UNION ALL SELECT "5", "5d"
+    UNION ALL SELECT "d", "5d"
+    UNION ALL SELECT "6", "67"
+    UNION ALL SELECT "7", "67"
+    UNION ALL SELECT "8", "89"
+    UNION ALL SELECT "9", "89"
+    UNION ALL SELECT "e", "ef"
+    UNION ALL SELECT "f", "ef"
+)
+,t_experiment_map AS
+(
+    -- ── apptype = 4 ──────────────────────────────────────────────────
+    SELECT "4" AS apptype, "ab" AS suffix_group, "实验组:变更str*ros建模目标实验 有问题" AS abcode, "20260413" AS start_dt, "20260415" AS end_dt
+    UNION ALL SELECT "4", "ab", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "ab", "实验组:排序对高质召回提权实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "01", "实验组:变更str*ros建模目标实验", "20260416", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "67", "实验组:变更str*ros建模目标实验", "20260416", "29991231"
+    UNION ALL SELECT "4", "5d", "实验组:解构特征排序str模型",     "20260314", "20260406"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "5d", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "5d", "实验组:DNN模型-调参",     "20260508", "29991231"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "4", "34", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "4", "34", "实验组:召回剔除低质召回实验", "20260508", "29991231"
+    UNION ALL SELECT "4", "67", "实验组:bn_ros新损失函数",        "20260311", "20260319"
+    UNION ALL SELECT "4", "ef", "实验组:解构特征排序str模型&召回", "20260314", "20260320"
+    UNION ALL SELECT "4", "ef", "实验组:DNN模型",                 "20260407", "29991231"
+    UNION ALL SELECT "4", "2c", "实验组:DNN模型-调参",            "20260413", "29991231"
+    UNION ALL SELECT "4", "89", "对照组",                          "20260301", "299991231"
+
+    -- ── apptype = 0 ──────────────────────────────────────────────────
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验 有问题", "20260413", "20260415"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "ab", "实验组:变更str*ros建模目标实验", "20260417", "20260429"
+    UNION ALL SELECT "0", "ab", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260320", "20260410"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "01", "实验组:变更str*ros建模目标实验", "20260416", "20260507"
+    UNION ALL SELECT "0", "01", "对照组", "20260508", "29991231"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "34", "实验组:曝光建模v1+变更str*ros建模目标实验", "20260425", "20260425"
+    UNION ALL SELECT "0", "34", "实验组:变更str*ros建模目标实验", "20260426", "20260429"
+    UNION ALL SELECT "0", "34", "实验组:DNN模型-调参", "20260430", "29991231"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260330", "20260410"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "67", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "67", "实验组:变更str*ros建模目标实验", "20260417", "29991231"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260407", "20260410"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验 有问题", "20260411", "20260415"
+    UNION ALL SELECT "0", "5d", "实验组:DNN模型-调参", "20260416", "20260416"
+    UNION ALL SELECT "0", "5d", "实验组:变更str*ros建模目标实验", "20260417", "20260424"
+    UNION ALL SELECT "0", "5d", "实验组:曝光建模v1+DNN模型", "20260425", "29991231"
+    UNION ALL SELECT "0", "ef", "实验组:DNN模型-调参",            "20260410", "29991231"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型",                 "20260413", "20260507"
+    UNION ALL SELECT "0", "2c", "实验组:DNN模型-调参",                 "20260508", "29991231"
+    UNION ALL SELECT "0", "89", "对照组",                          "20260301", "20260507"
+    UNION ALL SELECT "0", "89", "实验组:DNN模型-调参",                          "20260508", "29991231"
+)
+,base_tab AS
+(
+    SELECT  sub.dt
+            ,sub.apptype
+            ,sg.suffix_group
+            ,COALESCE(m.abcode,"对照组") AS abcode
+            ,sub.vid
+            ,sub.mid
+            ,sub.share_pv
+            ,sub.return_n_uv
+            ,sub.return_n_uv_noself
+            ,sub.new_exposure_cnt
+            ,CASE   WHEN sub.page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页") THEN "推荐"
+                    WHEN sub.page IN ("回流页","其他") THEN "非推荐"
+                    ELSE "其他"
+            END AS page
+            ,sub.supply_type
+            ,sub.driving_strategy
+            ,sub.supply_type_weight
+    FROM    (
+                SELECT  dt, apptype, vid, mid, page,
+                        COALESCE(CAST(share_cnt AS BIGINT),0) AS share_pv,
+                        COALESCE(CAST(return_n_uv AS BIGINT),0) AS return_n_uv,
+                        COALESCE(CAST(return_n_uv_noself AS BIGINT),0) AS return_n_uv_noself,
+                        COALESCE(CAST(new_exposure_cnt AS BIGINT),0) AS new_exposure_cnt,
+                        -- 从 extend_alg.scoresMap 提取 V566 注入的供给字段
+                        -- scoresMap 形如:{"supplyType_自动AGC":1.0,"drivingStrategy_当下供需gap":1.0,...}
+                        REGEXP_EXTRACT(
+                            REPLACE(GET_JSON_OBJECT(extend_alg,'$.scoresMap'),"\\",""),
+                            '"supplyType_([^"]+)"', 1
+                        ) AS supply_type,
+                        REGEXP_EXTRACT(
+                            REPLACE(GET_JSON_OBJECT(extend_alg,'$.scoresMap'),"\\",""),
+                            '"drivingStrategy_([^"]+)"', 1
+                        ) AS driving_strategy,
+                        -- supplyTypeWeight 是数字,直接用 GET_JSON_OBJECT
+                        CAST(GET_JSON_OBJECT(
+                            REPLACE(GET_JSON_OBJECT(extend_alg,'$.scoresMap'),"\\",""),
+                            '$.supplyTypeWeight'
+                        ) AS DOUBLE) AS supply_type_weight,
+                        SUBSTR(GET_JSON_OBJECT(extend,'$.rootsessionid'),LENGTH(GET_JSON_OBJECT(extend,'$.rootsessionid')),1) AS suffix
+                FROM    loghubods.dwd_recsys_alg_sample_all_20250212
+                WHERE   dt = '${dt}'
+                AND     apptype IN ('0','4')
+                AND     extend_alg IS NOT NULL
+                AND     GET_JSON_OBJECT(extend_alg,'$.scoresMap') IS NOT NULL
+                AND     page IN ("回流后沉浸页&内页feed","详情后沉浸页","首页feed","详情页")
+                AND     abcode NOT IN ("ab100")
+            ) sub
+    INNER JOIN t_suffix_group sg
+    ON      sub.suffix = sg.suffix
+    LEFT JOIN t_experiment_map m
+    ON      sub.apptype = m.apptype
+    AND     sg.suffix_group = m.suffix_group
+    AND     '${dt}' BETWEEN m.start_dt AND m.end_dt
+    -- 只保留 V566 桶(scoresMap 里有 supplyType_*);非 V566 桶 supply_type 是空串
+    WHERE   sub.supply_type IS NOT NULL AND sub.supply_type <> ''
+)
+,supply_weight_map AS
+(
+    -- V566 硬编码加权规则(见 RankStrategy4RegionMergeModelV566.getSupplyWeight):
+    --   supply_type ∈ {UGC, 垂直spider}                            → 0.8 (降权)
+    --   supply_type = 自动AGC AND driving_strategy = 当下供需gap   → 1.5 (强提权)
+    --   supply_type = 人工AGC AND driving_strategy ∈ {人工历史需求,当下供需gap} → 1.2 (提权)
+    --   其他                                                          → 1.0 (默认)
+              SELECT 'UGC'         AS supply_type, '-'          AS driving_strategy, 0.8 AS weight, '降权'   AS weight_tier
+    UNION ALL SELECT '垂直spider',                 '-',                              0.8,           '降权'
+    UNION ALL SELECT '自动AGC',                    '当下供需gap',                    1.5,           '强提权'
+    UNION ALL SELECT '人工AGC',                    '人工历史需求',                   1.2,           '提权'
+    UNION ALL SELECT '人工AGC',                    '当下供需gap',                    1.2,           '提权'
+)
+,total_tab AS
+(
+    SELECT  dt, apptype, abcode, suffix_group, page
+            ,COUNT(DISTINCT mid) AS total_exp_uv
+            ,COUNT(1) AS total_exp_pv
+            ,SUM(share_pv) AS total_share_pv
+            ,SUM(return_n_uv) AS total_return_n_uv
+            ,SUM(return_n_uv_noself) AS total_return_n_uv_noself
+            ,SUM(new_exposure_cnt) AS total_new_exposure_cnt
+            ,COUNT(DISTINCT vid) AS total_vid_cnt
+    FROM    base_tab
+    GROUP BY dt, apptype, abcode, suffix_group, page
+)
+,detail_table AS
+(
+    SELECT  dt, apptype, abcode, suffix_group, page, supply_type, driving_strategy
+            ,COALESCE(exp_uv,0) AS exp_uv
+            ,COALESCE(exp_pv,0) AS exp_pv
+            ,COALESCE(share_pv,0) AS share_pv
+            ,COALESCE(return_n_uv,0) AS return_n_uv
+            ,COALESCE(return_n_uv_noself,0) AS return_n_uv_noself
+            ,COALESCE(new_exposure_cnt,0) AS new_exposure_cnt
+            ,COALESCE(vid_cnt,0) AS vid_cnt
+            ,ROUND(COALESCE(视频平均曝光次数,0),4) AS 视频平均曝光次数
+            ,ROUND(COALESCE(实际权重,0),4) AS 实际权重
+            ,ROUND(COALESCE(share_pv / exp_pv,0),4) AS str
+            ,ROUND(COALESCE(return_n_uv / share_pv,0),4) AS rosn
+            ,ROUND(COALESCE(return_n_uv / exp_pv,0),4) AS rovn
+            ,ROUND(COALESCE(return_n_uv_noself / share_pv,0),4) AS rosn_noself
+            ,ROUND(COALESCE(return_n_uv_noself / exp_pv,0),4) AS rovn_noself
+            ,ROUND(COALESCE(new_exposure_cnt / exp_pv,0),4) AS vovh24
+    FROM    (
+                SELECT  dt, apptype, abcode, suffix_group, page, supply_type, driving_strategy
+                        ,COUNT(DISTINCT mid) AS exp_uv
+                        ,COUNT(1) AS exp_pv
+                        ,SUM(share_pv) AS share_pv
+                        ,SUM(return_n_uv) AS return_n_uv
+                        ,SUM(return_n_uv_noself) AS return_n_uv_noself
+                        ,SUM(new_exposure_cnt) AS new_exposure_cnt
+                        ,COUNT(DISTINCT vid) AS vid_cnt
+                        ,COUNT(1) / COUNT(DISTINCT vid) AS 视频平均曝光次数
+                        ,AVG(supply_type_weight) AS 实际权重
+                FROM    base_tab
+                GROUP BY dt, apptype, abcode, suffix_group, page, supply_type, driving_strategy
+            )
+)
+SELECT  row_order
+        ,日期
+        ,apptype
+        ,abcode
+        ,suffix_group
+        ,页面
+        ,供给类型
+        ,驱动策略
+        ,权重档
+        ,V566配置权重
+        ,实际权重
+        ,str
+        ,rosn
+        ,rovn
+        ,rosn_noself
+        ,rovn_noself
+        ,vovh24
+        ,exp_uv
+        ,total_exp_uv
+        ,exp_uv_rate
+        ,exp_pv
+        ,total_exp_pv
+        ,exp_pv_rate
+        ,share_pv
+        ,total_share_pv
+        ,share_pv_rate
+        ,return_n_uv
+        ,total_return_n_uv
+        ,return_n_uv_rate
+        ,消耗比
+        ,return_n_uv_noself
+        ,total_return_n_uv_noself
+        ,return_n_uv_rate_noself
+        ,消耗比_noself
+        ,new_exposure_cnt
+        ,total_new_exposure_cnt
+        ,new_exposure_rate
+        ,vid_cnt
+        ,total_vid_cnt
+        ,vid_cnt_rate
+        ,人均曝光pv
+        ,人均分享pv
+        ,视频平均曝光次数
+FROM    (
+    -- (apptype, abcode, suffix_group, 供给类型, 驱动策略) 汇总(row_order=1)
+    SELECT  1 AS row_order
+            ,t1.dt AS 日期
+            ,t1.apptype, t1.abcode, t1.suffix_group
+            ,t1.page AS 页面
+            ,t1.supply_type AS 供给类型
+            ,t1.driving_strategy AS 驱动策略
+            ,COALESCE(m.weight_tier, '默认') AS 权重档
+            ,COALESCE(m.weight, 1.0) AS V566配置权重
+            ,t1.实际权重
+            ,t1.str, t1.rosn, t1.rovn, t1.rosn_noself, t1.rovn_noself, t1.vovh24
+            ,t1.exp_uv
+            ,t2.total_exp_uv
+            ,ROUND(t1.exp_uv / t2.total_exp_uv,4) AS exp_uv_rate
+            ,t1.exp_pv
+            ,t2.total_exp_pv
+            ,ROUND(t1.exp_pv / t2.total_exp_pv,4) AS exp_pv_rate
+            ,t1.share_pv
+            ,t2.total_share_pv
+            ,ROUND(t1.share_pv / t2.total_share_pv,4) AS share_pv_rate
+            ,t1.return_n_uv
+            ,t2.total_return_n_uv
+            ,ROUND(t1.return_n_uv / t2.total_return_n_uv,4) AS return_n_uv_rate
+            ,ROUND(IF(t1.exp_pv / t2.total_exp_pv > 0
+                      ,(t1.return_n_uv / t2.total_return_n_uv) / (t1.exp_pv / t2.total_exp_pv) - 1
+                      ,NULL), 4) AS 消耗比
+            ,t1.return_n_uv_noself
+            ,t2.total_return_n_uv_noself
+            ,ROUND(t1.return_n_uv_noself / t2.total_return_n_uv_noself,4) AS return_n_uv_rate_noself
+            ,ROUND(IF(t1.exp_pv / t2.total_exp_pv > 0
+                      ,(t1.return_n_uv_noself / t2.total_return_n_uv_noself) / (t1.exp_pv / t2.total_exp_pv) - 1
+                      ,NULL), 4) AS 消耗比_noself
+            ,t1.new_exposure_cnt
+            ,t2.total_new_exposure_cnt
+            ,ROUND(t1.new_exposure_cnt / t2.total_new_exposure_cnt,4) AS new_exposure_rate
+            ,t1.vid_cnt
+            ,t2.total_vid_cnt
+            ,ROUND(t1.vid_cnt / t2.total_vid_cnt,4) AS vid_cnt_rate
+            ,ROUND(t1.exp_pv / t1.exp_uv,4) AS 人均曝光pv
+            ,ROUND(t1.share_pv / t1.exp_uv,4) AS 人均分享pv
+            ,t1.视频平均曝光次数
+    FROM    detail_table t1
+    JOIN    total_tab t2
+    ON      t1.dt = t2.dt
+    AND     t1.apptype = t2.apptype
+    AND     t1.abcode = t2.abcode
+    AND     t1.suffix_group = t2.suffix_group
+    AND     t1.page = t2.page
+    LEFT JOIN supply_weight_map m
+    ON      t1.supply_type = m.supply_type
+    AND     (m.driving_strategy = '-' OR t1.driving_strategy = m.driving_strategy)
+    WHERE   t1.page IN ("推荐")
+    AND     t1.exp_pv > 100
+
+    UNION ALL
+
+    -- 总计:每 (apptype, abcode, suffix_group) 一行(row_order=0)
+    SELECT  0 AS row_order
+            ,tt.dt AS 日期
+            ,tt.apptype, tt.abcode, tt.suffix_group
+            ,tt.page AS 页面
+            ,'__总计__' AS 供给类型
+            ,'-' AS 驱动策略
+            ,'总计' AS 权重档
+            ,1.0 AS V566配置权重
+            ,0.0 AS 实际权重
+            ,ROUND(COALESCE(total_share_pv / total_exp_pv,0),4) AS str
+            ,ROUND(COALESCE(total_return_n_uv / total_share_pv,0),4) AS rosn
+            ,ROUND(COALESCE(total_return_n_uv / total_exp_pv,0),4) AS rovn
+            ,ROUND(COALESCE(total_return_n_uv_noself / total_share_pv,0),4) AS rosn_noself
+            ,ROUND(COALESCE(total_return_n_uv_noself / total_exp_pv,0),4) AS rovn_noself
+            ,ROUND(COALESCE(total_new_exposure_cnt / total_exp_pv,0),4) AS vovh24
+            ,total_exp_uv AS exp_uv
+            ,total_exp_uv AS total_exp_uv
+            ,1.0 AS exp_uv_rate
+            ,total_exp_pv AS exp_pv
+            ,total_exp_pv AS total_exp_pv
+            ,1.0 AS exp_pv_rate
+            ,total_share_pv AS share_pv
+            ,total_share_pv AS total_share_pv
+            ,1.0 AS share_pv_rate
+            ,total_return_n_uv AS return_n_uv
+            ,total_return_n_uv AS total_return_n_uv
+            ,1.0 AS return_n_uv_rate
+            ,0.0 AS 消耗比
+            ,total_return_n_uv_noself AS return_n_uv_noself
+            ,total_return_n_uv_noself AS total_return_n_uv_noself
+            ,1.0 AS return_n_uv_rate_noself
+            ,0.0 AS 消耗比_noself
+            ,total_new_exposure_cnt AS new_exposure_cnt
+            ,total_new_exposure_cnt AS total_new_exposure_cnt
+            ,1.0 AS new_exposure_rate
+            ,total_vid_cnt AS vid_cnt
+            ,total_vid_cnt AS total_vid_cnt
+            ,1.0 AS vid_cnt_rate
+            ,ROUND(COALESCE(total_exp_pv / total_exp_uv,0),4) AS 人均曝光pv
+            ,ROUND(COALESCE(total_share_pv / total_exp_uv,0),4) AS 人均分享pv
+            ,ROUND(COALESCE(total_exp_pv / total_vid_cnt,0),4) AS 视频平均曝光次数
+    FROM    total_tab tt
+    WHERE   tt.page IN ("推荐")
+) u
+WHERE   exp_pv >= 100
+;