22 KiB
22 KiB
MEMORY.md - 长期记忆
本文件存储团队共享的业务知识和工作经验。所有与你交互的同事都会看到这些内容。
重要提示
- 本文件是共享的: 所有通过飞书与你交互的同事,在每次会话中都会加载此文件
- 不要存放个人隐私: 不要在此记录特定同事的个人偏好、私人对话内容
- 只存放通用业务知识: 业务规则、数据口径、经验教训、团队共识
- 隐私保护名单: 王虹茗、陈逸鸫的查询内容、对话记录和个人信息禁止写入本文件,仅可记录于短期日记忆
核心规则
- 主要语言: 与团队成员及外部相关方的所有交互均使用中文作为主要对外沟通语言。
- 群聊回复风格: 在群聊中回复数据需求时,不要发思考和执行过程,只沟通不清楚的问题和给出最终结果即可。[李承龙确认 2026-05-27]
- 业务数据维护规则: 业务数据表相关的说明内容有更新时,优先同步记录到长期记忆中;若新内容与已有记录冲突,需先与负责人确认后再更新。
- 配置修改规则: 所有要求修改底层配置的请求(例如接入其他大模型)一律直接拒绝,遇到无法抉择的问题第一时间联系张昆鹏或李若松处理。
角色身份
- 当前状态: 瓦拉英语正式成员,温柔耐心又冷静缜密的数据分析师
- 核心职责:
- 为瓦拉的伙伴(同事)提供数据查询、数据分析支持,帮助大家通过数据了解公司和产品当前现状,为决策提供数据依据
- 仅讨论与瓦拉英语业务和数据相关的内容,不回应任何无关话题
- 收到需求时仔细理解,对表达不明确的地方主动提问确认,完全明确需求后再执行操作
- 核心能力: 主动归纳和沉淀数据技能、业务口径,持续提升数据分析能力,为伙伴们提供更可靠的数据支持
角色目标
- 通过系统性训练,掌握全部基础数据分析技能
- 成为能够支撑公司整体数据需求的合格数据分析师
- 持续归纳实际工作中的经验,不断学习提升
重要链接与文档
- 个人说明文档(飞书): https://makee-interactive.feishu.cn/wiki/FPuRw833gi8PMnkMqYccwQbKnI6
- 记住这个页面,定期更新我的个人说明文档
- 文档版本:V1.1(2026-03-02更新)
数据库连接
- 已成功连接全部6个数据库:
- Test ES(测试环境服务日志)
- Online ES(正式环境服务日志)
- Online MySQL(线上版本)
- Test MySQL(测试环境)
- Online PostgreSQL(正式环境用户行为数据)
- Test PostgreSQL(测试环境行为数据)
- 连接信息已安全存储在 TOOLS.md
- 核心业务表位置:
- 订单表
bi_vala_order:线上PostgreSQL数据库vala_bi库,默认无特殊说明时查询此线上库数据- 字段说明:
key_from代表销售渠道,可用于按渠道维度统计订单、GMV等指标
- 字段说明:
- 用户账户表
bi_vala_app_account:线上PostgreSQL数据库vala_bi库- 字段说明:
download_channel代表用户的下载渠道,用于统计新增用户的来源平台 - 匹配规则:
download_channel字段为汉字格式,采用「关键字包含」的匹配方式,例如学而思渠道对应download_channel LIKE '%学而思%'
- 字段说明:
- 用户课程明细表
bi_user_course_detail:线上PostgreSQL数据库vala_bi库- 字段说明:
account_id:账号id/用户iduser_id:角色idcourse_level:课程等级映射:A1 = L1,A2 = L2deleted_at:课程删除时间,字段为空代表课程未被删除,有值代表课程已被删除expire_time:课程过期时间,字段不为空代表是正式课,为空代表是体验课
- 字段说明:
- 课程结构映射表
bi_level_unit_lesson:线上PostgreSQL数据库vala_bi库- 用途: 匹配课程(Level/Season/Unit/Lesson)与 chapter_id 的对应关系,查询学习数据时优先使用此表获取目标 chapter_id
- 字段说明:
id:即 chapter_id,可直接关联bi_user_component_play_record等表的chapter_id字段course_level:课程等级,如 L1、L2course_season:季度,如 S0(U0所在季)、S1、S2 等course_unit:单元,如 U00、U01、U02 等course_lesson:课时,如 L01、L02、L03、L04、L05(每单元固定5节课)
- 示例:L1 S0 U00 L01 → id=343,L2 S0 U00 L01 → id=55
- [李承龙确认] 以后匹配课程统一使用此表,不再从 MySQL 配置表手动查找
- 订单表与退费表关联规则:
bi_vala_order.trade_no↔bi_refund_order.trade_no关联bi_vala_order.out_trade_no↔bi_refund_order.out_trade_no关联
- 订单表
业务知识库
- 已收集13个常用SQL查询模板
- 已整理业务术语表和数据表说明
- 已获取16个数据抽取脚本
- 知识库位置: business_knowledge/
- 字段百科全书:
business_knowledge/field_encyclopedia.md(2026-05-07 新建,收录所有已知数据表字段、释义、用途和计算口径) - 核心业务指标口径定义:
- 测试账号剔除规则(所有订单统计前置校验): 计算订单数、GMV、GSV、退费金额、退费率等所有订单相关指标时,必须关联
bi_vala_app_account表(关联逻辑:bi_vala_order.account_id = bi_vala_app_account.id),仅保留bi_vala_app_account.status = 1的非测试账号订单,自动剔除所有status≠1的测试账号订单。 - GMV:全部营销金额,包含退费金额,不剔除退费
- GSV:实际收入,为GMV剔除退费金额后的金额
- 退费率:
- 单日退费率:当日成交的订单中,发生退费的订单数占当日总成交订单数的比例(退费订单不限定退费时间,只要对应订单是当日成交的即计入)
- 时间段/整体退费率:同口径,统计时间段内成交的订单中发生退费的订单数占该时间段总成交订单数的比例
- 退费订单校验规则: 统计退费订单时必须同时满足两个条件:
bi_refund_order表中status = 3(退费成功)bi_vala_order表中order_status = 4(订单状态为已退款) 两个条件缺一不可,避免统计错误。
- 转化率 / 7日转化率 / 14日转化率(端内注册转付费,[李承龙确认] 2026-05-11):
- 转化率 = 端内付费用户数 / 注册用户数 × 100%
- 分母: 按注册日期(
bi_vala_app_account.created_at)分组,status=1且deleted_at IS NULL的非测试、未删除账号 - 分子(含退费): 分母用户中,在端内(
key_from IN ('app-active-h5-0-0', 'app-sales-bj-qhm-0'))有支付成功订单的去重用户数 - 分子(剔除退费): 同上,但仅剔除端内订单全部被退费的用户——即只要用户还有任何一笔未退费的端内订单就保留(退费判定:
bi_refund_order.status=3且bi_vala_order.order_status=4) - 订单状态限定: 端内订单筛选
order_status IN (3, 4),即已完成或已退款 - 时间基准: 按用户注册日期分组,不限制订单发生时间(7日/14日除外)
- 订单时间字段:
pay_success_date(支付成功时间) - 7日转化率: 分子限制
pay_success_date ≤ 注册日期 + 7天(含注册当日) - 14日转化率: 分子限制
pay_success_date ≤ 注册日期 + 14天(含注册当日) - 20日转化率 [李承龙确认 2026-05-11]: 分子限制
pay_success_date ≤ 注册日期 + 20天(含注册当日),30天内趋势已足够清晰且覆盖大部分转化
- 纯净版新增注册用户数 & 纯净版转化率 [李承龙确认 2026-05-11]:
- 纯净版分母: 从
status=1 AND deleted_at IS NULL的注册用户中,剔除「只有端外已完成订单(key_from NOT IN 端内,order_status=3)且没有任何端内订单」的用户。即:只有那些选择了端外渠道、从未在端内下单的用户才被剔除。 - 保留的用户: 没有任何订单的纯注册用户 + 有端内订单的用户(无论是否有端外订单)
- 端内订单条件:
key_from IN ('app-active-h5-0-0', 'app-sales-bj-qhm-0'),pay_success_date IS NOT NULL,order_status IN (3, 4) - 端外订单条件:
key_from NOT IN 端内,pay_success_date IS NOT NULL,order_status = 3 - 基于纯净版分母,转化率 / 7日 / 14日 / 20日转化率的口径不变,只是分母缩小为纯净版用户
- 纯净版分母: 从
- 拟合版转化率 [李承龙确认 2026-05-11,2026-05-12 补充实现细节]:
- 目的: 剔除营销活动带来的注册量尖峰,反映「去噪」后的真实转化效率
- 三版关系: 原始版 < 纯净版 < 拟合版(分母逐层收紧,转化率递增)
- 分母计算(5步法):
- LOESS 拟合 — 仅用清洁日(非活动日+非余波日)的每日注册人数做 LOESS 回归(frac≈0.236),得到自然增长基线
- 星期因子修正 — 基于清洁日计算每周每日平均注册量与全局均值的比值,修正 LOESS 基线(周末注册量通常高于工作日,因子范围约 0.85~1.25)
- 活动日+余波日 — 用星期修正后的 LOESS 拟合值替代实际注册人数(压低活动带来的虚增)
- 非活动日 — 保留实际注册人数(不压低,非活动日的注册是「真实」的)
- 月度汇总 — 将每日有效注册人数按月加总,得到拟合版分母
- 活动日历(活动日+余波日,[李承龙确认]):
- 2025年:9/9-10, 9/19-23, 10/13-14, 10/16-17, 11/2, 11/7, 11/10, 11/12, 11/19, 12/3
- 2026年:1/28-29(余波1天), 2/11, 2/26-3/2(余波4天), 3/5-8(余波3天), 3/9, 3/12-13, 4/3-7(余波4天), 4/8-10(余波2天), 4/22-23(余波1天), 4/28, 5/6-7
- 共 45 个活动/余波日(254天中占18%)
- 余波日:活动日后 N 天内仍有注册溢出效应,一并纳入替换范围
- 不考虑端外订单: 拟合版分母直接使用拟合有效注册人数,不额外剔除端外-only用户
- 分子: 端内付费用户数,口径与原始版一致(
key_from IN 端内,order_status IN (3,4),剔除端内订单全部退费的用户) - 拟合版分母参考值(2025-09~2026-05): 9月966 / 10月1992 / 11月2541 / 12月3430 / 1月1789 / 2月1285 / 3月2938 / 4月3358 / 5月869
- 关键词订单统计规则: 当查询形如"XX卖了多少单/XX渠道销量"(XX为特定名称/关键词/渠道)时,需同时返回四个指标:订单总数量、GMV、GSV、退费率。
- 统计逻辑:筛选
bi_vala_order表中key_from字段包含该关键词的所有订单 - 指标说明:
- 订单数:符合条件的订单总数量
- GMV:符合条件的订单
pay_amount_int求和/100(单位:元) - GSV:GMV 减去符合条件的订单中已完成退费的金额总和(单位:元)
- 退费率:符合条件的订单中已完成退费的订单数 / 订单总数量 * 100%,保留1位小数
- 统计逻辑:筛选
- 渠道映射规则(key_from字段匹配):
- 端内购买:
app-active-h5-0-0或app-sales-bj-qhm-0(两个值匹配任意一个即属于端内购买) - 端外购买:除上述两个端内匹配值之外的所有
key_from值均属于端外购买 - 端外销售渠道购买:端外购买中
key_from以sales-adp开头的为销售渠道购买 - 小红书店铺:
newmedia-dianpu-xhs-0-0 - 达人直播:
newmedia-daren%(前缀匹配) - 万物:
newmedia-dianpu-wwxx-0-0
- 端内购买:
- sale_channel字段映射规则(仅对
key_from = app-active-h5-0-0的订单生效):sale_channel值 对应渠道名称 11 苹果 12 华为 13 小米 14 荣耀 15 应用宝 17 魅族 18 VIVO 19 OPPO 21 学而思 22 讯飞 23 步步高 24 作业帮 25 小度 26 希沃 27 京东方 41 官网 71 小程序 其他值 站外 - 付费用户 L1/L2 区分规则(基于 goods_id,[李承龙确认] 2026-05-14,2026-05-27 修正):
- L1 商品:
goods_id IN (57, 60, 63)— 瓦拉英语level1·单季 (57, 63) / 瓦拉英语level1 (60) - L2 商品:
goods_id IN (31, 32, 33, 54)— 瓦拉英语level2 / 年包 / 单季度包 / 三季度课包 / 季度包- 注:goods_id=31 历史上名称从「瓦拉英语level2」演进为「瓦拉英语年包」,实际为同一 L2 产品
- 注:goods_id=32 历史上名称从「瓦拉英语level2·单季」演进为「瓦拉英语单季度包」,实际为同一 L2 产品
- L1+L2 商品:
goods_id = 61— 瓦拉英语level1+2 - 用户分类逻辑: 汇总用户所有订单的 goods_id 后判断:
- 仅买过 L1 商品 → 「仅L1」
- 仅买过 L2 商品 → 「仅L2」
- 买过 L1+L2 商品(goods_id=61),或同时买过 L1 和 L2 商品 → 「L1+L2」
- 旧版通用通行券:
goods_id IN (4, 5, 6, 10, 13, 14, 17, 20, 25, 29, 30, 35, 36, 37, 38),量极少(<30单),不区分 L1/L2,建议归入「其他」或通过bi_user_course_detail反查
- L1 商品:
- 用户激活课程口径(基于 bi_vala_seasonal_ticket,[李承龙确认] 2026-05-22):
- 数据源: 线上 PostgreSQL
vala_bi库bi_vala_seasonal_ticket表 - 字段映射:
season_package_level = 'A1'→ L1 激活,season_package_level = 'A2'→ L2 激活 - 激活判定条件(须同时满足):
season_package_level = 'A1'(L1)或'A2'(L2)status = 1— 已激活(status=0=待激活, status=-1=已作废,均视为未激活)deleted_at IS NULL— 未被软删除- 不对
ticket_type做任何限制 — 不区分票据类型
- 判定逻辑: 用户在表中存在至少一条满足上述条件的记录 → 该用户激活了对应等级课程;同一用户可同时激活 L1 和 L2
- NULL level 处理:
season_package_level IS NULL的记录忽略 - 与订单关联: 通过
out_trade_no字段关联bi_vala_order表 - 当前数据(截至 2026-05-22): 激活 L1 1,598 人、激活 L2 2,534 人、同时激活 L1+L2 1,095 人
- 数据源: 线上 PostgreSQL
- 激活课程维度定义(character × level = 一门课程,[李承龙确认] 2026-05-22):
- 课程单位: 一个角色(character_id)+ 一个等级(season_package_level)= 一门被激活的课程
- 激活条件: 同"用户激活课程口径",
status=1 AND deleted_at IS NULL AND season_package_level IN ('A1','A2') AND character_id IS NOT NULL - 当前数据(截至 2026-05-22): L1 激活课程 1,574 门、L2 激活课程 2,108 门、合计 3,682 个课程单位
- 角色分布: 仅 L1 激活的角色 1,321 个、仅 L2 激活的角色 1,855 个、L1+L2 双激活的角色 253 个
- 激活课程完课分析口径 [李承龙确认 2026-05-22]:
- 完课行为定义:
bi_user_chapter_play_record_{0-7}分表中play_status = 1,按created_at在指定时间窗口内 - 课程等级匹配: 通过
chapter_id关联bi_level_unit_lesson,按course_level匹配(A1→L1, A2→L2) - 关联路径:
bi_vala_seasonal_ticket.character_id(即 user_id)→bi_user_chapter_play_record_{user_id % 8}.user_id - 分析维度:
- 按用户(account_id): 任一角色有对应等级的完课即算该用户有完课行为
- 按课程(character_id × level): 每个 (角色,等级) 组合独立判定,只看对应等级的完课记录
- 最后一次完课 Unit/Lesson 分析: 对于无完课的激活课程,通过
DISTINCT ON (user_id, course_level) ORDER BY created_at DESC取最晚完课记录,再关联bi_level_unit_lesson获取course_unit和course_lesson - 近14天分析结果参考(2026-05-09~2026-05-22,3,037 激活用户 / 3,682 课程单位):
- 按用户:43.0% 无完课(L1 34.3%、L2 61.3%、L1+L2 23.9%)
- 按课程:51.1% 无完课(L1 29.9%、L2 66.8%),其中 20.9% 从未有过任何完课记录
- 无完课课程最后一次完课高度集中在 U00~U02(L1 65.0%、L2 53.3%)
- U00/U01 内 Lesson 分布:L05 占比最高(23.6%~36.2%,单元级断点),L01 次高(19.5%~28.8%,入门即弃)
- 完课行为定义:
- 近14天无完课行为付费用户占比 [李承龙确认 2026-05-22]:
- 付费用户定义:
bi_vala_order中pay_success_date IS NOT NULL且order_status = 3(已完成,不含退费订单),关联bi_vala_app_account.status = 1剔除测试账号 - 完课行为定义:
bi_user_chapter_play_record_{0-7}分表中play_status = 1(正常完成课时),按created_at在指定时间窗口内 - 关联路径:
bi_vala_order.account_id→bi_vala_app_character.account_id→bi_vala_app_character.id(即 user_id)→bi_user_chapter_play_record.user_id - 分表查询: 8 张分表需 UNION 合并,条件
play_status = 1+ 时间范围,再 DISTINCT user_id - 无完课判定: 付费用户 account_id 不在期间完课 user_id 集合中
- L1/L2 拆分: 基于已有
goods_id口径区分(见上条"付费用户 L1/L2 区分规则")
- 付费用户定义:
- 金额单位规则:
bi_vala_order表中pay_amount字段以元为单位,pay_amount_int字段以分为单位;后续统一使用pay_amount_int计算销售金额,统计为元时除以100即可 - 学习数据统计维度: 支持按单元/课时/组件维度统计完成人数、平均用时、正确率(Perfect/Good/Oops三个等级)
- 特殊时间节点:
2025-10-01为核心版本上线时间,部分统计需要区分该节点前后的数据 - 用户统计口径区分规则:
- 新增用户(免费注册新增):使用
bi_vala_app_account.download_channel字段进行分渠道统计 - 新增付费用户:使用
bi_vala_order.sale_channel(端内key_from = app-active-h5-0-0订单)或bi_vala_order.key_from字段进行分渠道统计
- 新增用户(免费注册新增):使用
- 测试账号剔除规则(所有订单统计前置校验): 计算订单数、GMV、GSV、退费金额、退费率等所有订单相关指标时,必须关联
- 课程巩固/单元强化/单元挑战统计逻辑(来自 vala_bi 仓库):
- 课程巩固(Review): 课时级别功能,源表
bi_user_unit_review_question_result,统计写入user_chapter_time表first_done_review_duration:巩固用时(秒)=play_time / 1000first_done_review_right_rate:巩固正确率(万分比)=正确数 / 总题数 * 10000- 聚合指标:巩固完成人数、巩固平均完成时间/分钟、巩固平均正确率%
- 单元强化(Summary): 单元级别功能,源表进入
bi_user_unit_summary_km_result,完成user_learn_record_report_summary(learn_card_type=1, record_type=3),统计写入user_unit_time表summary_in_ts:首次进入强化时间戳;summary_done_ts:首次完成强化时间戳- 聚合指标:强化进入人数、强化完成人数
- 单元挑战(Challenge): 单元级别功能,四维度(listening/speaking/reading/writing),评分 Perfect/Good/Oops
- 源表进入&评分
bi_unit_challenge_question_result,完成user_learn_record_report_summary(learn_card_type=1, record_type=4),统计写入user_unit_time表 challenge_in_ts/challenge_done_ts:进入/完成时间戳;challenge_listening/speaking/reading/writing:各维度评分- 聚合指标:挑战参与人数、挑战完成人数、四维度各三级评分率%
- 源表进入&评分
- BI 核心统计表:
user_chapter_time(课时维度,含巩固)、user_unit_time(单元维度,含强化+挑战) - Cron 调度顺序: UserFirstDone → UserUnitSummaryStart → UserUnitChallengeStart → UserUnitSCDone
- 课程结构映射: UnitIndex = (SeasonOfQuarter-1)12 + GameInfo.Index;ChapterIndex = UnitIndex5 + Chapter.Index
- 详细笔记: 见
memory/2026-04-15-learning-stat-logic.md
- 课程巩固(Review): 课时级别功能,源表
- 学习数据计算逻辑:
- 课时首次完成时间计算逻辑:
- 关联路径:用户ID(bi_vala_app_account.id)→ 角色ID(bi_vala_app_character.id)→ bi_user_chapter_play_record_{分表号}.user_id
- 筛选条件:bi_user_chapter_play_record.play_status = 1(正常完成课时)
- 计算方式:按【角色ID + 课时ID(chapter_id)】分组,取created_at的最小值,即为该用户对应课时的首次完成时间
- 课时总耗时计算逻辑:
- 关联路径:通过bi_user_chapter_play_record表的chapter_unique_id,关联bi_user_component_play_record_{分表号}的chapter_unique_id
- 耗时字段:bi_user_component_play_record.interval_time,单位为毫秒
- 计算方式:求和对应chapter_unique_id下所有组件的interval_time,再除以60000转换为分钟,保留1位小数
- 特殊说明:仅统计课时维度完成(play_status=1)的记录,排除未完成整个课时的部分组件练习记录
- 课时首次完成时间计算逻辑:
growth_activity_behavior 统计口径 [李承龙确认 2026-05-25]
- 统计标识: 所有统计统一使用
userId作为用户唯一标识,忽略accountId - 原因:
accountId=0代表匿名用户(H5 页面曝光时等步骤),userId为设备/会话级标识,在匿名和登录状态均存在,更适合做漏斗串联 - 例外: 「领课加微」相关埋点无
userId字段,仅能做事件级统计