xiaowei-system/skills/devops/devops-umbrella/references/gaokao-site/database-structure-and-data...

8.8 KiB
Raw Blame History

数据库结构 & 数据完整性

Last updated: 2026-06-21 Reason: Updated fill rates after backfill; added school name matching and cascade backfill references

关联参考

完整审计方法论含数据质量、JSON 覆盖分析、plan_type 分类优化建议)→ references/database-audit-methodology.md 可复用审计脚本9 点全面检查scp 后直接跑)→ scripts/gaokao-audit.py 学校名匹配安全做法(勿用字符串包含匹配!)→ references/school-name-matching.md 数据回填方法论(级联传播,旧名映射)→ references/data-backfill-methodology.md

数据库文件

/www/wwwroot/gaokao/gaokao_henan.db35MBSQLite

不是 gaokao.dbschools.db(后两个是空文件,遗留产物)。

两张核心表

schools 表 — 院校投档分(聚合级别)

CREATE TABLE schools (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    year INTEGER,
    school_name TEXT,
    school_code TEXT,
    subject TEXT,          -- 物理类 / 历史类
    batch TEXT,            -- 本科批 / 专科批
    plan_type TEXT,        -- 普通类 / 中外合作办学 / 国家专项 / 地方专项 / 应用工程学院 / 莫动理工学院
    subject_group TEXT,    -- 专业组代码 (101)(102) 等
    subject_req TEXT,      -- 选科要求
    plan_count INTEGER,    -- 招生人数
    min_score INTEGER,     -- 投档分
    min_rank INTEGER,      -- 投档位次
    batch_diff INTEGER,    -- 批次线差
    sch_id TEXT,           -- 院校代码(从招生章程导入)
    tuition TEXT           -- 学费(静态推算)
);

2025 年覆盖: 1,437 所学校 / 7,437 条记录

majors 表 — 分专业录取数据

CREATE TABLE majors (
    -- 字段名需通过查阅,列清单:
    school_name, major, major_code, subject_group, subject_req,
    plan_count, min_score, min_rank, location, school_type,
    is_985, is_211, subject, batch, year, major_note
);

2024 年覆盖: 2,244 所学校 (数据源更全) 2025 年覆盖: 830 所学校 / 24,524 条记录 ⚠️ 仅河南招生院校

数据完整性分析

majors 表 2024→2025 数量变化

数据源自河南省教育考试院官方发布的 分专业录取数据。不同年份发布范围不同:

年份 学校数 记录数 说明
2024 2,244 全国范围较全的院校数据
2025 830 24,524 仅2025年在河南有招生计划的院校

两年交集: 811 所学校同时存在于 2024 和 2025 年。其中:

  • 19 所学校 仅 2025 年有2025 年新招生/新发布)
  • 1,433 所学校 仅 2024 年有2025 年未发布数据)

误区澄清:有些人误以为"2024年2,244所与2025年830所完全无交集"实际并非如此——大部分811/830是交叠的。2024 年数据量更大是因为那年的数据源覆盖了更多院校,而非两年之间的学校完全不同。

数据源文件(从用户处获取):

文件名 用途 2025 年数据量
22-25年全国高校在河南的专业录取分数.xlsx majors 表数据源 24,524 条 / 830 校
22-25年全国高校在河南的院校录取分数.xlsx schools 表数据源 7,437 条 / 1,437 校
22-25年全国高校在河南的招生计划.xlsx 招生计划(非录取分) 60,836 条(含学制、学费)

字段填充率2026-06-21 级联回填后)

majors 表 is_985 / is_211 / school_type / location

年份 回填前 回填后 方法
2017-2019 44-48% 96% 从2024/2025按学校名传播含59所更名校旧名映射
2020-2021 68-69% 98% 同上
2022-2025 100% 100% 原始数据完整

schools 表关键字段

字段 回填前 回填后
school_code 48.5% 97.5%
tuition 48.5% 97.5%
batch_diff 41.5% 95.4%
plan_type 48.5% 87.7%
sch_id 47.7% 86.6%

school_basic.json 覆盖2025年 830所学校

匹配方式 数量 占比
精确匹配 816 98.3%
括号标准化后匹配(代码层) 10 1.2%
别名映射(校区变体) 4 0.5%
完全无数据 0 0%
合计覆盖 830 100%

更新记录59所更名校key改为新名+保留old_name50所新学校补充省份/性质。

字段名陷阱batch 命名差异2024 vs 2025

这是回退查询时的常见陷阱。 河南省高考 2025 年改革前后,数据库中的 batch 字段命名发生了变化:

年份 本科批次名称 说明
2025 及以后 本科批 新高考合并本科批次
2024 及以前 本科一批 / 本科二批 旧高考分批次

影响所有回退查询。例如 _get_recommended_majors_for_student 中查询 2024 年数据时:

# 错误:使用当前 batch='本科批' 查 2024 年
conn.execute("SELECT ... FROM majors WHERE year=2024 AND batch=?", (_batch,))
# 返回 0 条,即使有数据

# 正确:同时尝试三种 batch 名称
conn.execute("SELECT ... FROM majors WHERE year=2024 AND (batch='本科一批' OR batch='本科二批' OR batch='本科批')")

学校类型检测策略v3.1 确立)

school_basic.jsontypetags 字段不可靠——有民办学校被标为 type='综合'tags=['双一流'](如武汉东湖学院、河北科技学院)。

正确策略:数据库 majors.school_type 优先。

优先级 来源 覆盖范围 可靠性
1 majorsschool_type 2,302 所 原始数据源
2 school_basic.type 公办类型列表 后备 仅用于推断公办
3 description 正则分析 后备 有历史语境误判

_determine_school_type regex 陷阱

基于 description 的学校类型正则容易假阳性:

误匹配模式 描述原文 结果 正确
(创办的).{0,30}(民办|私立) "孔祥熙创办的私立铭贤学堂"1907年历史 民办 公办

v3.1 已从正则中移除 创办的|管理的|。仅保留:

(是一所|作为|转设为|批准为|举办的|批准成立的).{0,30}(民办|私立)

验证 batch 命名差异

sqlite3 /www/wwwroot/gaokao/gaokao_henan.db \
  "SELECT batch, COUNT(*) as cnt FROM majors \
   WHERE school_name='河南科技大学' AND year=2024 AND subject='理科' \
   GROUP BY batch ORDER BY cnt DESC LIMIT 5;"
# 预期:本科一批 / 本科二批(不是"本科批"

回退方案2026-06-20 已实施)

当用户查询 2025 年数据但数据库中没有时:

  1. school_search API (gaokao_chat_server_v2.py:1380):优先查 year=2025无数据回退到 MAX(year),返回 actual_year + 每条记录带 year 字段
  2. major_search API (gaokao_chat_server_v2.py:1448):查询指定年份 → 0 条结果 → 自动降级到最近有数据的年份,返回 actual_year
  3. school.html 前端:搜索结果上方显示 📅 当前数据来源2025年(正常)或黄色文字提示回退年份
  4. major.html 前端:回退时显示黄色提示条 ⚠️ 2025年暂无数据已自动切换到 2024年数据

验证方法

# 按年份检查 schools 表学校数
sqlite3 /www/wwwroot/gaokao/gaokao_henan.db "SELECT year, COUNT(DISTINCT school_name) as schools, COUNT(*) as records FROM schools GROUP BY year ORDER BY year;"

# 按年份检查 majors 表学校数
sqlite3 /www/wwwroot/gaokao/gaokao_henan.db "SELECT year, COUNT(DISTINCT school_name) as schools, COUNT(*) as records FROM majors GROUP BY year ORDER BY year;"

# 检查 2024 与 2025 年 majors 交集(验证是否真无交集)
sqlite3 /www/wwwroot/gaokao/gaokao_henan.db "SELECT COUNT(DISTINCT m1.school_name) FROM majors m1 JOIN majors m2 ON m1.school_name=m2.school_name AND m1.year=2024 AND m2.year=2025;"

# 仅 2025 年有的学校(新招生)
sqlite3 /www/wwwroot/gaokao/gaokao_henan.db "SELECT DISTINCT school_name FROM majors WHERE year=2025 AND school_name NOT IN (SELECT DISTINCT school_name FROM majors WHERE year=2024);"

# 仅 2024 年有的学校(未发布数据)
sqlite3 /www/wwwroot/gaokao/gaokao_henan.db "SELECT COUNT(DISTINCT school_name) FROM majors WHERE year=2024 AND school_name NOT IN (SELECT DISTINCT school_name FROM majors WHERE year=2025);"

# 测试回退
curl -s 'http://127.0.0.1:8080/api/major/search?school=河南科技大学&subject=物理类&year=2025'
# 预期: actual_year=2024, majors 有数据

curl -s 'http://127.0.0.1:8080/api/school/search?q=河南科技大学&subject=物理类'
# 预期: actual_year=2025, 每条记录有 year 字段