4. 案例结构化建模
前三节我们解决了“标签怎么定、案例怎么收”的问题。但收上来的案例如果只是几段文字描述,或者一张随手截的赔率图,那么它既无法批量检索,也无法做统计对比,更谈不上支撑后续的相似案例匹配。本节要做的,是把一场盘口案例拆成可存储、可关联、可查询的结构化字段,并建立案例主表与关联表之间的关系模型。
先明确一个基本判断:一场盘口案例天然是“一对多”的。一场比赛只有一个赛果,但盘口时序有多个时间点,赔率变化涉及多家公司、多个玩法,标签也可能有多个。因此不能把所有信息塞进一张宽表,而应采用“主表 + 关联表”的拆分思路。主表承载比赛级唯一信息,关联表承载随时间或对象变化的多值信息。
一、字段拆解:四类信息分别落到哪里
按题目要求,案例可拆为比赛信息、盘口时序、赔率变化、赛果四类。下面给出一个可直接落地的字段设计示例(字段名为示例命名,实际可按团队规范调整):
| 信息类别 | 承载表 | 关键字段示例 | 说明 |
|---|---|---|---|
| 比赛信息 | 案例主表 case_main | case_id、联赛、主队、客队、开赛时间、主队排名、客队排名、赛前状态标签 | 一场比赛一行,case_id 为主键 |
| 盘口时序 | 盘口时序表 case_handicap | case_id、记录时间、盘口值、水位主、水位客、盘口方向 | 同一场比赛多条,按时间排序 |
| 赔率变化 | 赔率变化表 case_odds | case_id、公司、玩法、记录时间、初赔、即时赔、变化幅度 | 按公司×玩法×时间多维记录 |
| 赛果 | 赛果表 case_result | case_id、全场比分、半场比分、胜负结果、盘口结果、大小球结果 | 一场比赛一行,与主表一对一 |
这里有两个容易踩坑的地方。第一,盘口方向必须统一约定。建议全文统一采用“以主队视角为正”的约定:盘口值为正表示主队让球,为负表示主队受让,水位则分别记录主客两侧。若团队习惯用“让球方视角”,必须在字段注释中写死,否则后续统计会出现方向翻转的错误。第二,时间字段要记录绝对时间而非“赛前几小时”,因为“赛前几小时”依赖开赛时间,一旦开赛时间调整就会失真;相对时间可在查询时用开赛时间减去记录时间动态计算。
二、关系模型:主表与关联表如何连接
四张表通过 case_id 建立关联:主表与赛果表是一对一,主表与盘口时序表、赔率变化表是一对多。标签不建议直接以字符串塞进主表,而应单独建标签关联表 case_tag(case_id、tag_id、标注人、置信度),这样同一案例可挂多个标签,也便于按标签反查案例。下图展示了这一关系模型的结构与连接方向:
图中箭头方向表示“主表记录指向其关联记录”,即从 case_main 的 case_id 出发,可以向下找到该案例的全部盘口时点、赔率记录、唯一赛果和多个标签。反过来,从任一关联表也能通过 case_id 回溯到主表,这正是后续“按标签查案例、按盘口形态查案例”的基础。
三、一次完整的拆解示例
假设我们采集到一场示例比赛(以下数据为教学示例,非真实赛事):主队排名第 3、客队排名第 11,开赛时间 2024-03-16 20:00。主表写入一行,case_id 记为 C20240316001。盘口时序表记录三个时点:赛前 24 小时主让 0.5 球、主水 0.92;赛前 6 小时升至主让 0.75 球、主水 1.02;赛前 1 小时回落至主让 0.5 球、主水 0.85。赔率变化表按“公司×玩法×时点”写入,例如某公司欧赔初赔 1.85/3.40/4.20,即时赔 1.78/3.50/4.50,变化幅度字段可由即时赔减初赔计算得到。赛果表记录全场 2:1、半场 1:0,胜负为主胜,盘口结果为主让 0.5 球赢盘,大小球按 2.5 球线判为大球。标签关联表则挂上“升盘后回落”“临场降水”两个标签。
这样拆解后,一条查询就能回答过去只能靠翻笔记的问题。例如要统计“升盘后回落且临场降水”的案例胜率,只需在 case_tag 中筛出对应 tag_id,关联 case_result 统计盘口结果分布;要观察这类案例的盘口轨迹,则关联 case_handicap 按记录时间排序即可还原曲线。字段拆分的价值,正在于让这些查询成为可能。
四、落地时的几个判断
第一,不要过度拆表。如果团队案例量只有几百条,把标签直接做成主表的一个多值字段也能用;但一旦要做标签交叉统计,独立标签关联表几乎是必需的。第二,关联表要保留原始值而非只存计算结果。变化幅度可以算,但初赔和即时赔必须原样保留,否则后续想换一种幅度定义就无法重算。第三,字段命名和方向约定要写进数据字典,尤其是盘口正负号、水位归属、时间基准三项,这是盘口案例库最容易产生歧义的地方。把这三项约定清楚,主表与关联表的关系模型才真正可用,而不是停留在纸面上。