我应该为抽认卡应用程序使用单独的表吗?

时间:2011-11-21 22:00:52

标签: php mysql database-design

我正在为一个flashcards应用程序设计一个MySQL数据库。我有一个名为“课程”的表,我在那里保存课程的ID,名称和描述以及一个叫做项目的表格,我保留了所有的抽认卡。表项保留了唯一的ID,课程ID,以及问题,答案和更多详细信息。还有一个名为重复的表,我存储用户记忆的闪卡的数据。如果我想获得一个用户尚未记忆的flashcard,我用LEFT JOIN查询数据库,这样我就可以从闪存卡中获取所有数据,并从匹配的重复中获取行。但是,我必须指定某个闪卡所属的课程,所以我的查询看起来更像是:

SELECT * 
    FROM (SELECT * 
              FROM flashcards 
              WHERE course='coursename') AS flashcards 
        LEFT JOIN repetitions 
            ON flashcards.id=repetitions.flashcardid 
    WHERE repetitions.lastrepetition IS NULL 
    LIMIT 1;

为每门课程设置分离表会不会更好,所以我不必指定我的意思?那会加快数据库的速度吗?将不会有很多课程(约10-20),每门课程将包含大约5k-10k的抽认卡。

抱歉,我忘了说,如果用户没有记住抽认卡,表格重复中就不会有任何等效记录。我实际做的是: 我选择所有的闪光灯WHERE coursename ='coursename', 2.我选择所有重复WHERE user ='user'和coursename ='coursname, 3.然后我LEFT JOIN第一个表中的记录和第二个表中的记录。我从某个课程中获得所有的抽认卡,其中一些记录在重复表中有相应的部分, 4.然后我使用WHERE重复IS NULL,我只得到那些在重复表中没有它们的uqivalents的抽认卡。

    SELECT * FROM
    (SELECT * FROM flashcards WHERE course='coursename') AS f
    LEFT JOIN
    (SELECT * FROM repetitions WHERE user='user' AND course='coursename') AS r
    ON f.id=r.flashcardid
    WHERE repetitions IS NULL LIMIT 1)

以上查询工作正常,但我想知道如果有更多人使用该应用程序,是否不需要太多内存/内存。

我唯一更好的解决方案是从闪存卡表中仅选择ID并将LIMIT设置为用户限制(假设每个会话30个闪卡)。然后我将使用此查询而不是30次。我可以在GET变量中传递id。 (该解决方案的唯一问题是,如果用户在他的PC上研究抽认卡然后移动到移动设备并忘记关闭PC的会话并返回到PC,则可能会覆盖一些重复。无论如何,这将是一个非常罕见的案例,但仍有可能。)


感谢您的帮助!你的建议实际上是正确的。我刚弄明白我犯了什么错误 - 在我原来的查询中,我不必要地添加了'WHERE repetitions.course ='coursename'的条件。 但是,我仍然需要在右表中使用括号来确定用户。

SELECT * FROM flashcards AS f
LEFT JOIN (SELECT * FROM repetitions WHERE user='username') AS r
ON f.id=r.flashcardid
WHERE f.course='coursename' AND r IS NULL

2 个答案:

答案 0 :(得分:0)

你不应该将课程分成自己的表格。

你不能做这样的事吗?

select * from flashcards
left join repititions
  on flashcards.id = repititions.flashcardid
where course = 'coursename' 
and repititions.lastrepitition is null
limit 1

答案 1 :(得分:0)

我认为没有理由为每门课程添加单独表格的开销和头痛。此外,不需要该子查询。您的查询可以写成:

SELECT *
    FROM flashcards f
        LEFT JOIN repetitions r
            ON f.id = r.flashcardid
    WHERE f.course = 'coursename'
        AND r.lastrepetition IS NULL
    LIMIT 1;