You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quiz系统user_quiz表关联与数据库规范化问题咨询

Hey there! Let's work through your Quiz system database design challenge together—this is a common spot to get stuck, so let's break it down clearly.

1. First, Fix That Primary Key Issue

Using userid as the sole primary key for user_quiz means each user can only have one record here. That works if you only need to store a running total of completed quizzes and total score, but it's not great for tracking individual quiz attempts (like when a user finished a specific quiz, or their score on that exact quiz).

For better normalization and future flexibility, I'd split this into two parts:

  • A detailed attempt table to log every quiz a user completes
  • A summary table (or view) to hold the aggregated totals you need
2. Foreign Key Associations Done Right

Assuming you already have a users table (with primary key userid) and a quizzes table (with primary key quizid), here are two solid approaches:

Option 1: Track Every Individual Attempt (High Normalization)

This is the most scalable approach, as it preserves all historical data. Create a user_quiz_attempts table:

CREATE TABLE user_quiz_attempts (
    attempt_id INT AUTO_INCREMENT PRIMARY KEY,
    userid INT NOT NULL,
    quizid INT NOT NULL,
    score INT NOT NULL,
    completed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    -- Foreign keys to link to core tables
    FOREIGN KEY (userid) REFERENCES users(userid) ON DELETE CASCADE,
    FOREIGN KEY (quizid) REFERENCES quizzes(quizid) ON DELETE CASCADE,
    -- Optional: Prevent users from retaking the same quiz (remove if retakes are allowed)
    UNIQUE KEY (userid, quizid)
);

To get the total completed quizzes and score for a user, just run an aggregate query:

SELECT 
    userid,
    COUNT(quizid) AS completed_quiz_count,
    SUM(score) AS total_score
FROM user_quiz_attempts
GROUP BY userid;

If you need to pull these stats frequently, turn that query into a view so you can access it like a table:

CREATE VIEW user_quiz_stats AS
SELECT 
    userid,
    COUNT(quizid) AS completed_quiz_count,
    SUM(score) AS total_score
FROM user_quiz_attempts
GROUP BY userid;

Option 2: Store Only Aggregated Totals (Simple Use Cases)

If you don't need to track individual attempts and just want the running totals, you can keep your original user_quiz table—just make sure the foreign key is set up correctly:

CREATE TABLE user_quiz (
    userid INT PRIMARY KEY,
    completed_quiz_count INT NOT NULL DEFAULT 0,
    total_score INT NOT NULL DEFAULT 0,
    FOREIGN KEY (userid) REFERENCES users(userid) ON DELETE CASCADE
);

In this case, every time a user finishes a quiz, you'll run an UPDATE query to increment the count and add the new score instead of inserting a new record.

3. Key Normalization Rules to Follow
  • 1NF (Atomic Values): Never store multiple quiz scores or IDs in a single field. Each record should represent one attempt (or one user's totals, in the simple case).
  • 2NF (Eliminate Partial Dependencies): If you use a composite primary key (like userid + quizid in the attempt table), make sure all other fields (like score) depend on the entire key, not just part of it.
  • 3NF (Eliminate Transitive Dependencies): Don't store redundant data—for example, don't put the quiz name in user_quiz_attempts; pull it from the quizzes table using the quizid foreign key instead.
4. Quick Extensibility Tips
  • If you want to allow retakes, remove the UNIQUE KEY (userid, quizid) constraint from the attempt table.
  • Add an is_passed BOOLEAN field to the attempt table if you need to track which quizzes a user passed.
  • For more complex quizzes (like multiple questions), add a user_quiz_answers table linked to attempt_id to log each question's answer and whether it was correct.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:51:39