# 全字段大表

**获取时间:** 2026-03-02
**飞书文档 Token:** VVyWd5491o6tuqxceCVci6dVnFd

## 业务说明

这个查询将用户、购课、角色、课程完课等多个维度的数据整合在一起，形成一个宽表，适合进行综合分析。

## 涉及的数据表

1. **bi_vala_app_account** - 用户账号表
2. **account_detail_info** - 账号详情表
3. **bi_vala_order** - 订单表
4. **bi_vala_app_character** - 角色表
5. **bi_user_chapter_play_record_0~7** - 用户章节播放记录表（分表）
6. **bi_level_unit_lesson** - 课程单元表
7. **bi_user_component_play_record_0~7** - 用户组件播放记录表（分表）

## SQL 查询

```sql
select a.id as "用户ID"
        ,a.created_date as "注册日期"
        ,a.download_channel as "下载渠道"
        ,a.key_from as "下载key_from"
        ,b.login_address as "城市"
        ,b.phone_login as "是否手机登录"
        ,c.sale_channel as "购课渠道"
        ,case when c.sale_channel is NULL then '未购课'
                                when c.sale_channel = '站外' then '站外购课'
                                else '站内购课'
                         end as "购课标签"
        ,c.key_from as "购课key_from"
        ,c.pay_date as "购课日期"
        ,c.pay_amount as "购课金额"
        ,d.id as "角色ID"
        ,d.characer_pay_status as "角色是否付费"
        ,d.gender as "性别"
        ,2026 - cast(d.birthday as int) as "年龄"
        ,e.chapter_id as "课程ID"
        ,e.course_id as "课程名称"
        ,e.chapter_unique_id as "完课标识"
        ,e.finish_date as "完课日期"
        ,e.finish_time as "完课耗时"
from 
(
        select id
                                ,key_from
                                ,to_char(created_at,'YYYY-MM-DD') as created_date
                                ,download_channel
        from bi_vala_app_account
        where status = 1
        and id not in (51,2121)
        and deleted_at is NULL
        group by id
                                        ,key_from
                                        ,created_at
                                        ,download_channel
) as a 
left join
(
        select account_id
                                ,split_part(login_address,'-',2) as login_address
                                ,case when phone_login_times = 0 then 0
                                                        else 1
                                                        end as phone_login
        from account_detail_info
        group by account_id
                                        ,login_address
                                        ,case when phone_login_times = 0 then 0
                                                                else 1
                                                                end
) as b on a.id = b.account_id
left join 
(
        select account_id
                                ,case when sale_channel = 11 then '苹果'
                                                        when sale_channel = 12 then '华为'
                                                        when sale_channel = 13 then '小米'
                                                        when sale_channel = 14 then '荣耀'
                                                        when sale_channel = 15 then '应用宝'
                                                        when sale_channel = 17 then '魅族'
                                                        when sale_channel = 18 then 'VIVO'
                                                        when sale_channel = 19 then 'OPPO'
                                                        when sale_channel = 21 then '学而思'
                                                        when sale_channel = 22 then '讯飞'
                                                        when sale_channel = 23 then '步步高'
                                                        when sale_channel = 24 then '作业帮'
                                                        when sale_channel = 25 then '小度'
                                                        when sale_channel = 26 then '希沃'
                                                        when sale_channel = 27 then '京东方'
                                                        when sale_channel = 41 then '官网'
                                                        when sale_channel = 71 then '小程序'
                                                        else '站外'
                                 end as sale_channel
                                ,key_from
                                ,to_char(pay_success_date,'YYYY-MM-DD') as pay_date
                                ,pay_amount
        from bi_vala_order
        where order_status = 3
        and pay_amount_int > 49800
        group by account_id
                                        ,case when sale_channel = 11 then '苹果'
                                                                when sale_channel = 12 then '华为'
                                                                when sale_channel = 13 then '小米'
                                                                when sale_channel = 14 then '荣耀'
                                                                when sale_channel = 15 then '应用宝'
                                                                when sale_channel = 17 then '魅族'
                                                                when sale_channel = 18 then 'VIVO'
                                                                when sale_channel = 19 then 'OPPO'
                                                                when sale_channel = 21 then '学而思'
                                                                when sale_channel = 22 then '讯飞'
                                                                when sale_channel = 23 then '步步高'
                                                                when sale_channel = 24 then '作业帮'
                                                                when sale_channel = 25 then '小度'
                                                                when sale_channel = 26 then '希沃'
                                                                when sale_channel = 27 then '京东方'
                                                                when sale_channel = 41 then '官网'
                                                                when sale_channel = 71 then '小程序'
                                                                else '站外'
                                           end
                                        ,key_from
                                        ,pay_success_date
                                        ,pay_amount
) as c on a.id = c.account_id
left join 
(
        select id
                                ,account_id
                                ,case when purchase_season_package = '[1]' then 0
                                                        else 1
                                                        end as characer_pay_status
                                ,case when gender = 0 then 'girl'
                                                        when gender = 1 then 'boy'
                                                        else 'unknow'
                                                        end as gender
                                ,case when split_part(birthday,'-',1) = '' then '0000'
                                                        else split_part(birthday,'-',1)
                                                        end as birthday
        from bi_vala_app_character
        where deleted_at is NULL
        group by id
                                        ,account_id
                                        ,case when purchase_season_package = '[1]' then 0
                                                                else 1
                                                                end
                                        ,case when gender = 0 then 'girl'
                                                                when gender = 1 then 'boy'
                                                                else 'unknow'
                                                                end
                                        ,case when split_part(birthday,'-',1) = '' then '0000'
                                                                else split_part(birthday,'-',1)
                                                                end
) as d on a.id = d.account_id
left join 
(
        select user_id
                                ,chapter_id
                                ,format('%s-%s-%s-%s',course_level,course_season,course_unit,course_lesson) as course_id
                                ,x.chapter_unique_id
                                ,finish_date
                                ,format('%s:%s',floor(sum(interval_time)/1000/60),mod((sum(interval_time)/1000),60)) as finish_time
                                ,rank () over (partition by x.chapter_unique_id order by finish_date) as rankno
        from
        (
                select user_id
                                        ,chapter_id
                                        ,chapter_unique_id
                                        ,to_char(updated_at,'YYYY-MM-DD') as finish_date
                from bi_user_chapter_play_record_0
                where chapter_id in (55,56,57,58,59)
                and play_status = 1
                group by id
                                                ,user_id
                                                ,chapter_id
                                                ,chapter_unique_id
                                                ,updated_at
                union all
                select user_id
                                        ,chapter_id
                                        ,chapter_unique_id
                                        ,to_char(updated_at,'YYYY-MM-DD') as finish_date
                from bi_user_chapter_play_record_1
                where chapter_id in (55,56,57,58,59)
                and play_status = 1
                group by user_id
                                                ,chapter_id
                                                ,chapter_unique_id
                                                ,updated_at
                -- ... 其他分表类似
        ) as x
        left join
        (
                select cast(id as int) as id
                            ,course_level
                                        ,course_season
                                        ,course_unit
                                        ,course_lesson
                from bi_level_unit_lesson
                group by id
                                                ,course_level
                                                ,course_season
                                                ,course_unit
                                                ,course_lesson
        ) as y on x.chapter_id = y.id
        left join
        (
                select chapter_unique_id
                                        ,interval_time
                from bi_user_component_play_record_0
                group by chapter_unique_id
                                                ,interval_time
                -- ... 其他分表类似
        ) as z on x.chapter_unique_id = z.chapter_unique_id
        group by user_id
                                        ,chapter_id
                                        ,course_level
                                        ,course_season
                                        ,course_unit
                                        ,course_lesson
                                        ,x.chapter_unique_id
                                        ,finish_date
) as e on d.id = e.user_id
where rankno = 1
group by a.id
                                ,a.created_date
                                ,a.download_channel
                                ,a.key_from
                                ,b.login_address
                                ,b.phone_login
                                ,c.sale_channel
                                ,c.key_from
                                ,c.pay_date
                                ,c.pay_amount
                                ,d.id
                                ,d.characer_pay_status
                                ,d.gender
                                ,d.birthday
                                ,e.chapter_id
                                ,e.course_id
                                ,e.chapter_unique_id
                                ,e.finish_date
                                ,e.finish_time
```

## 重要业务逻辑

### 1. 购课渠道映射
```sql
case when sale_channel = 11 then '苹果'
     when sale_channel = 12 then '华为'
     -- ... 更多渠道
     when sale_channel = 71 then '小程序'
     else '站外'
end as sale_channel
```

### 2. 购课标签
```sql
case when c.sale_channel is NULL then '未购课'
     when c.sale_channel = '站外' then '站外购课'
     else '站内购课'
end as "购课标签"
```

### 3. 角色付费状态
```sql
case when purchase_season_package = '[1]' then 0
     else 1
end as characer_pay_status
```

### 4. 性别映射
```sql
case when gender = 0 then 'girl'
     when gender = 1 then 'boy'
     else 'unknow'
end as gender
```

### 5. 完课时间计算
```sql
format('%s:%s',floor(sum(interval_time)/1000/60),mod((sum(interval_time)/1000),60)) as finish_time
```

## 注意事项

1. **订单筛选条件**: `order_status = 3` and `pay_amount_int > 49800` (筛选有效订单且金额大于498元)
2. **分表处理**: 用户播放记录表按分表存储（0-7），需要使用 UNION ALL 合并
3. **去重逻辑**: 使用 `rank() over (partition by ... order by ...)` 取第一次完课记录
4. **测试用户排除**: `id not in (51,2121)`
