You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL数据库中存储测验题标签的最优方案咨询

最优标签存储方案:多对多数据库范式设计

这是典型的标签系统设计问题,最优解绝对是采用多对多关系的数据库范式设计,完美解决你提到的所有痛点:

核心表结构设计

你需要创建三个关联的表,彻底告别字符串拼接/拆分的繁琐操作:

1. 题目表(示例名:quizzes

存储测验题的核心内容,主键用自增ID:

CREATE TABLE quizzes (
    quiz_id INT AUTO_INCREMENT PRIMARY KEY,
    question_text TEXT NOT NULL,
    -- 其他字段:答案、难度等级等
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 标签表(示例名:tags

存储唯一的标签信息,确保标签不重复:

CREATE TABLE tags (
    tag_id INT AUTO_INCREMENT PRIMARY KEY,
    tag_name VARCHAR(100) UNIQUE NOT NULL, -- 唯一索引避免重复标签
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

3. 题目-标签关联表(示例名:quiz_tags

作为中间表,建立题目和标签的多对多关系,联合主键防止重复关联:

CREATE TABLE quiz_tags (
    quiz_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (quiz_id, tag_id), -- 确保一个题目不会重复绑定同一个标签
    FOREIGN KEY (quiz_id) REFERENCES quizzes(quiz_id),
    FOREIGN KEY (tag_id) REFERENCES tags(tag_id)
);

解决你的所有痛点

  • 便捷添加标签
    添加新标签时,先查询tags表判断标签是否存在,不存在则插入新标签,再将题目ID和标签ID插入关联表即可。前端可以配合标签选择器实现一键添加,完全不用处理字符串转换。
  • 精准查询带特定标签的题目
    再也不用依赖通配符查询,直接通过关联表精确匹配标签名称,比如查询带"Golf"标签的题目:
    SELECT q.question_text 
    FROM quizzes q
    JOIN quiz_tags qt ON q.quiz_id = qt.quiz_id
    JOIN tags t ON qt.tag_id = t.tag_id
    WHERE t.tag_name = 'Golf';
    
  • 清晰的标签列表
    直接查询tags表就能得到所有唯一标签,还能轻松统计每个标签的题目数量:
    SELECT t.tag_name, COUNT(qt.quiz_id) AS quiz_count
    FROM tags t
    LEFT JOIN quiz_tags qt ON t.tag_id = qt.tag_id
    GROUP BY t.tag_id, t.tag_name
    ORDER BY quiz_count DESC;
    

额外优化建议

  • 标签大小写统一:可以在插入标签时统一转为小写(比如LOWER(tag_name)),避免出现"Golf"和"golf"两个重复标签,查询时也统一转小写匹配。
  • 前端自动补全:从tags表拉取所有标签,实现输入时的自动补全,进一步降低重复标签的概率。
  • 数据迁移:针对现有7000道题的标签字符串,写个简单脚本拆分每个标签(按逗号分割),批量插入tags表(去重),再批量建立题目和标签的关联。

内容的提问来源于stack exchange,提问作者Robert Moritz

火山引擎 最新活动