# 销售线索企业邮品牌明细 (PySpark)

## Prompt
我需要你生成一段 PySpark 代码，产出"销售线索企业邮品牌明细"。

**业务背景与目标**：线下销售团队有一份三非企业的销售线索表（含 corpid 唯一键），数据仓库侧有一份每月统计的邮箱平台画像表（每个 corpid 多行，按 top_domain / domain_isp 维度统计当月被唤醒的不同别名邮箱数量）。运营想要的是：对每一个三非线索企业，把它的活跃邮箱（domain_alias_monthwakeup_uniq >= 1）提取出来，并且把底层细粒度的 domain_isp 字段（如 'cloud_a'、'mail_provider_n'、'biz' 等）映射成业务可识别的标准品牌（'电商平台A'、'邮件平台N'、'企业邮品牌C' 等），最终落到 DWD 层供下游使用。

**输入表**：
- `internal_platform_db.project_alpha_ods_tele_sale_clue_info_mysql_v3`
- `internal_platform_db.project_alpha_dws_ww_corpstat_usermail_v3`

**数据范围与过滤条件（业务说法）**：
  - 只保留有活跃邮箱的企业，即 b.domain_alias_monthwakeup_uniq >= 1。
  - 服务商不能为空，即 b.domain_isp IS NOT NULL。
  - 运行日期 ds 固定为 '20260513'，写到输出 imp_date 列。

**表关联关系**：
  - 子查询 a：`SELECT DISTINCT corpid FROM project_alpha_ods_tele_sale_clue_info_mysql_v3`（拿到所有三非线索企业的 corpid）。
  - inner join：a ⋈ project_alpha_dws_ww_corpstat_usermail_v3 b on a.corpid = b.corpid。

**聚合与计算规则（需体现在 SQL 中）**：
  1. 派生列 `domain_mx`（邮箱品牌），用 CASE WHEN 把 domain_isp 映射到标准品牌：      - 'other_zijian' → '其他自建'      - 'coremail_local' → 'coremail本地版'      - 'mail_provider_n' → '邮件平台N'      - IN ('outlook','outlook_cn') → 'outlook'      - IN ('cloud_a','ali','ecommerce_a','ecommerce_a') → '电商平台A'      - 'eyou_local' → '亿邮本地版'      - 'exchange_local' → 'exchange'      - 'coremail' → 'coremail saas版'      - IN ('263','263mail') → '263'      - 'postfix_local' → 'postfix本地版'      - 'collabf' → '协作平台F'      - 'biz' → '企业邮品牌C'      - ELSE → '其他saas'
  2. imp_date 字段固定填 '20260513'。

**输出要求**：
  - 目标表：`internal_platform_db.project_alpha_dwd_ww_tele_sale_corp_domain_mx_v3`
  - 输出表 schema（按此顺序、含义如下，5 列显式写出）：     1. imp_date STRING：运行日期 YYYYMMDD = '20260513'     2. corpid BIGINT：企业 ID     3. top_domain STRING：最多人使用的邮箱域名     4. domain_isp STRING：邮箱服务商底层标识（保留原值）     5. domain_mx STRING：CASE WHEN 派生的标准品牌
  - 写入策略：INSERT OVERWRITE TABLE，使用显式列名清单。
  - 沙箱化说明：原任务由 SparkBase 框架封装（job.load_dw_data + selectExpr 链路 + job.save_dw_data）；沙箱版改写为顶层 SparkSession + 一段 INNER JOIN + WHERE + CASE WHEN 的 SQL。
  - 如果目标表不存在，请先按 Hive 标准建表（ORC 存储），再写入数据。

## Reference Solution
# project_alpha rewrite-gt
# source: data/v7_gt_codes/case_row08_case_0028.py (v7 row 7, manifest_row 8)
# task_name: t_dwd_ww_tele_sale_corp_domain_mx_copilot
# rewrite rules:
#   1) internal_platform_db.ods_tele_sale_clue_info_mysql_copilot
#       -> internal_platform_db.project_alpha_ods_tele_sale_clue_info_mysql_v3
#   2) internal_platform_db.dws_ww_corpstat_usermail_copilot
#       -> internal_platform_db.project_alpha_dws_ww_corpstat_usermail_v3
#   3) internal_platform_db.dwd_ww_tele_sale_corp_domain_mx_copilot
#       -> internal_platform_db.project_alpha_dwd_ww_tele_sale_corp_domain_mx_v3
#   4) 删除 dw_spark_base_python3.SparkBase（沙箱无）：
#      - job = SparkBase() -> spark = SparkSession.builder...getOrCreate()
#      - job.load_dw_data(db, tbl).select/join/where/selectExpr 链路
#        -> 直接 spark.sql 写 INNER JOIN + WHERE + CASE WHEN 的完整 SELECT
#      - job.save_dw_data(df, db, tbl) -> spark.sql('INSERT OVERWRITE TABLE ...')
#      - job.statdate -> 硬编码 '20260513'
#   5) INSERT 用显式列名清单（5 列）避免列序错位
#   6) 沙箱表无分区，原 imp_date 分区列已沙箱化为普通列；本 GT 不读它
#      （原 GT 也不过滤 imp_date，是从全表读 → 沙箱表只灌目标 ds 即可）
# ---
from __future__ import print_function

import sys
from pyspark.sql import SparkSession


if __name__ == "__main__":
    ds = '20260513'

    spark = (
        SparkSession.builder
        .appName("project_alpha_dwd_ww_tele_sale_corp_domain_mx")
        .enableHiveSupport()
        .getOrCreate()
    )

    # 确保输出表以正确 schema 存在
    spark.sql("DROP TABLE IF EXISTS internal_platform_db.project_alpha_dwd_ww_tele_sale_corp_domain_mx_v3")
    spark.sql('''
CREATE TABLE internal_platform_db.project_alpha_dwd_ww_tele_sale_corp_domain_mx_v3 (
    `imp_date` STRING COMMENT '运行日期(YYYYMMDD)',
    `corpid` BIGINT COMMENT 'corpid',
    `top_domain` STRING COMMENT '最多人邮箱域名',
    `domain_isp` STRING COMMENT '邮箱服务商',
    `domain_mx` STRING COMMENT 'CASE WHEN 派生品牌'
) STORED AS ORCFILE
''')

    # 销售线索企业邮品牌明细
    sql = """
    INSERT OVERWRITE TABLE internal_platform_db.project_alpha_dwd_ww_tele_sale_corp_domain_mx_v3 (
        imp_date, corpid, top_domain, domain_isp, domain_mx
    )
    SELECT
        '{0}' as imp_date,
        b.corpid,
        b.top_domain,
        b.domain_isp,
        (CASE
            WHEN b.domain_isp = 'other_zijian' THEN '其他自建'
            WHEN b.domain_isp = 'coremail_local' THEN 'coremail本地版'
            WHEN b.domain_isp = 'mail_provider_n' THEN '邮件平台N'
            WHEN b.domain_isp IN ('outlook','outlook_cn') THEN 'outlook'
            WHEN b.domain_isp IN ('cloud_a','ali','ecommerce_a','ecommerce_a') THEN '电商平台A'
            WHEN b.domain_isp = 'eyou_local' THEN '亿邮本地版'
            WHEN b.domain_isp = 'exchange_local' THEN 'exchange'
            WHEN b.domain_isp = 'coremail' THEN 'coremail saas版'
            WHEN b.domain_isp IN ('263','263mail') THEN '263'
            WHEN b.domain_isp = 'postfix_local' THEN 'postfix本地版'
            WHEN b.domain_isp = 'collabf' THEN '协作平台F'
            WHEN b.domain_isp = 'biz' THEN '企业邮品牌C'
            ELSE '其他saas'
        END) AS domain_mx
    FROM (
        SELECT DISTINCT corpid
        FROM internal_platform_db.project_alpha_ods_tele_sale_clue_info_mysql_v3
    ) a
    INNER JOIN internal_platform_db.project_alpha_dws_ww_corpstat_usermail_v3 b
        ON a.corpid = b.corpid
    WHERE b.domain_alias_monthwakeup_uniq >= 1
      AND b.domain_isp IS NOT NULL
    """.format(ds)
    print("sql:")
    print(sql)
    spark.sql(sql)
    print("saved")

    spark.stop()
    sys.exit(0)