具有有限子查询的MySQL查询

时间:2012-03-19 23:59:46

标签: mysql sql ruby-on-rails

我正试图从几张表中获取一些统计数据。我们有一个用户表,测验表,一个测验问题集表和一个测验问题表。每个测验都有很多组,每组都有一个或多个问题。还有一个问题表,问题来自哪里(测验问题表将问题链接到问题集,然后链接到测验,然后链接到用户)。我需要的是看到正确回答的问题数量,以及回答的问题数量,但仅限于过去的50个问题。因此,如果一个用户回答了120个问题,则只能在此查询中使用最近的50个问题;如果用户回答了37个问题,那么应该使用他们的所有问题。我希望得到这个布局,所以还有user_id,questions_answered,questions_answered_correctly。我目前有这个工作,但我正在查看每个用户并抓住他们最近的50个问题,并且通过一些限制组织加入的其他表格,我必须做数百个,如果不是数千个这样的话来获得一个统计报告。< / p>

我猜我需要在某个地方做一个子查询,只从用户那里提取最新的问题,但我不确定这样的子查询是如何工作的。这是我到目前为止所拥有的,但我确信我完全不在此。它执行但不正确。有些结果超过50,不应该是:

SELECT users.id, (SELECT COUNT(grammar_quiz_questions.id) FROM `grammar_quiz_questions` 
INNER JOIN `grammar_quiz_question_sets` ON `grammar_quiz_question_sets`.`id` = `grammar_quiz_questions`.`grammar_quiz_question_set_id` 
INNER JOIN `grammar_quizzes` ON `grammar_quizzes`.`id` = `grammar_quiz_question_sets`.`grammar_quiz_id` 
INNER JOIN `grammar_questions` ON `grammar_questions`.`id` = `grammar_quiz_questions`.`grammar_question_id` 
WHERE (grammar_quiz_questions.finished is not null AND grammar_quizzes.user_id = users.id) 
ORDER BY grammar_quiz_questions.finished DESC LIMIT 50) AS `questions_answered`, (SELECT COUNT(grammar_quiz_questions.id) FROM `grammar_quiz_questions` 
INNER JOIN `grammar_quiz_question_sets` ON `grammar_quiz_question_sets`.`id` = `grammar_quiz_questions`.`grammar_quiz_question_set_id` 
INNER JOIN `grammar_quizzes` ON `grammar_quizzes`.`id` = `grammar_quiz_question_sets`.`grammar_quiz_id` 
INNER JOIN `grammar_questions` ON `grammar_questions`.`id` = `grammar_quiz_questions`.`grammar_question_id` 
WHERE (grammar_quiz_questions.finished is not null AND grammar_quizzes.user_id = users.id AND grammar_quiz_question_sets.correct_on_first_attempt = 1) 
ORDER BY grammar_quiz_questions.finished DESC LIMIT 50) AS `questions_answered_correctly`
FROM users

谢谢, 詹姆斯

1 个答案:

答案 0 :(得分:1)

更新:

更新后不是问题的完整答案,而是一些推动。我不确定你为什么要查询所有这些表格。是grammar_quiz_question_sets grammar_quiz_questions的互斥子集? grammar_quizzes和grammar_questions怎么样,设置关系是什么?鉴于我不知道这些答案,但是你知道,请看下面的代码片段。我希望它能指导你:

set @correct:=0;
select users.id, count(p.id), sum(if(r.correct_on_first_attempt = 1,1,0)) as correct 
from grammar_quiz_questions p, grammar_quiz_question_sets r, users;

ORIGINAL:

我想你有一个控制和数据访问层(java,php,python等),通过它来添加和操作记录。此外,我想你需要在用户的生命周期中多次获取统计信息。因此,虽然您可能需要像您这样的查询偶尔重新校准 - 如果这将是必要的 - ,您需要一些不那么令人头疼的东西。因此提出以下建议。

1]创建一个统计表:

create table statistics(
   user_id int(11) not null, -- foreign key
   questions_answered int(11) not null default 0,
   questions_answered_correctly int(11) no null default 0
   -- for primary key, you may use user_id or some auto record_id
)

2]第一次,运行“重/行政”查询

3]随后,在每次测验或每个回答问题后更新用户的统计数据。这里的想法是你将在内存中(即在编程层中)获得该信息,因为你必须更新测验表;在那段时间做一些数学来更新统计表。例如想象一下java:

public void updateStats(int userId, int questions, int correct){
    String query = 
    "insert into statistics(user_id,questions_answered,questions_answered_correctly) "+
    "values("+userId+", "+questions+", "+correct+") "+
     "on duplicate key update "+
     "questions_answered=questions_answered+values(questions_answered), "+
     "questions_answered_correctly = questions_answered_correctly + values(questions_answered_correctly)";
    ... //execute the statement

}

现在对于“沉重”的查询,我会更加清晰地重写它,以鼓励其他人抨击它:

SELECT users.id, 
(
SELECT COUNT(p.id) 
FROM grammar_quiz_questions p, grammar_quiz_question_sets r, grammar_quizzes t, grammar_questions u
WHERE r.id = p.grammar_quiz_question_set_id 
   AND t.id = r.grammar_quiz_id 
   AND u.id = p.grammar_question_id 
   AND p.finished is not null 
   AND t.user_id = users.id 
ORDER BY p.finished DESC LIMIT 50
) AS questions_answered,
(
SELECT COUNT(p.id) 
FROM grammar_quiz_questions p, grammar_quiz_question_sets r, grammar_quizzes t, grammar_questions u
WHERE r.id = p.grammar_quiz_question_set_id 
   AND t.id = r.grammar_quiz_id 
   AND u.id = p.grammar_question_id 
   AND p.finished is not null 
   AND t.user_id = users.id
   AND r.correct_on_first_attempt = 1 

订购完成DESC限制50    )AS questions_answered_correctly    来自用户