感谢您帮助我优化以下查询的客气话和智慧,因为我想使用"答案"表只有一次。同样,如果附带任何解释,我会很高兴。
SELECT
score.user_id,
name_email.NAME,
score.question_id,
TRUNCATE(GREATEST(0, SUM(answers.is_correct / IF(answers.is_correct = 1, possible_answers.good_answers, possible_answers.wrong_answers))) ,2) AS score
FROM score
INNER JOIN (
SELECT
id,
email,
CONCAT(users.f_name, " ", users.l_name) as NAME
FROM
users
)AS name_email
INNER JOIN answers
INNER JOIN (
SELECT
answers.question_id,
count(*) AS total_answers,
SUM(IF(is_correct = 1, 1, 0)) AS good_answers,
SUM(IF(is_correct = -1, 1, 0)) AS wrong_answers
FROM answers
GROUP BY answers.question_id
) AS possible_answers
WHERE score.answer_id = answers.id
AND possible_answers.question_id = score.question_id
AND score.user_id = name_email.id
-- AND score.user_id = 2
-- AND score.question_id = 1007
GROUP BY score.question_id, score.user_id
ORDER BY score.user_id, score.question_id
;
答案 0 :(得分:0)
注意所有查询(包括您的原始查询)都是通过在得分表上添加复合索引来改进的,如下所示:
ALTER TABLE `score` ADD INDEX `score_comp_uaq` (`user_id`, `answer_id`, `question_id`);
您的最终得分公式是指两种不同背景下的答案:
因此,避免两次使用答案表的一种方法是使用外部联接,这样我们就可以在一次访问中同时访问可能的和实际的。然而,在这种方法中,存在一个问题,即知道用户尝试了哪些问题,同时减少了答案表上的传递,它需要2次分数表。
SELECT
d.user_id
, CONCAT(users.f_name, " ", users.l_name) as NAME
, d.question_id
, d.good_answers
, d.wrong_answers
, d.possible_good
, d.possible_wrong
, COALESCE((d.good_answers / NULLIF(d.possible_good,0)),0) x
, COALESCE((d.wrong_answers / NULLIF(d.possible_wrong,0)),0) y
FROM (
SELECT
u.user_id
, a.question_id
, SUM(case when s.user_id IS NOT NULL AND a.is_correct = 1 then 1 else 0 end) AS good_answers
, SUM(case when s.user_id IS NOT NULL AND a.is_correct =-1 then 1 else 0 end) AS wrong_answers
, SUM(case when a.is_correct = 1 then 1.0 else 0.0 end) AS possible_good
, SUM(case when a.is_correct =-1 then 1.0 else 0.0 end) AS possible_wrong
from answers a
INNER join (select distinct user_id, question_id from score) u
ON a.question_id = u.question_id
left join score s ON u.user_id = s.user_id
AND a.question_id = s.question_id
AND a.id = s.answer_id
GROUP BY
u.user_id
, a.question_id
) d
INNER JOIN users ON d.user_id = users.id
;
虽然这可能是一个选项,但我相信下一个查询会提供更好的解释计划:
SELECT
s.user_id
, CONCAT(users.f_name, " ", users.l_name) as NAME
, s.question_id
, s.good_answers
, s.wrong_answers
, pa.possible_good
, pa.possible_wrong
, COALESCE((s.good_answers / NULLIF(pa.possible_good,0)),0) x
, COALESCE((s.wrong_answers / NULLIF(pa.possible_wrong,0)),0) y
FROM (
select
score.user_id
, answers.question_id
, count(*) AS total_answers
, SUM(IF(is_correct = 1, 1, 0)) AS good_answers
, SUM(IF(is_correct = -1, 1, 0)) AS wrong_answers
from score
INNER JOIN answers ON score.answer_id = answers.id
GROUP BY
score.user_id
, answers.question_id
) s
INNER JOIN (
SELECT
answers.question_id
, count(*) AS total_answers
, SUM(IF(is_correct = 1, 1.0, 0.0)) AS possible_good
, SUM(IF(is_correct = -1, 1.0, 0.0)) AS possible_wrong
FROM answers
GROUP BY answers.question_id
) AS pa ON s.question_id = pa.question_id
INNER JOIN users ON s.user_id = users.id
;
请注意,我没有尝试重现您的最终成绩"式。我觉得您可能希望在看到这些选项后修改您的操作方式,但列别名" x"和" y"应该允许你安排最终的公式。
This SQLfiddle可让您检查上述内容和原始内容。
第一次查询:
+----+-------------+-------+--------+------------------------------------------------------+----------------+---------+------------------+------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+--------+------------------------------------------------------+----------------+---------+------------------+------+----------+----------------------------------------------+
| 1 | PRIMARY | | ALL | | | | | 4 | 100.00 | |
| 1 | PRIMARY | users | eq_ref | PRIMARY | PRIMARY | 4 | d.user_id | 1 | 100.00 | |
| 2 | DERIVED | | ALL | | | | | 4 | 100.00 | Using where; Using temporary; Using filesort |
| 2 | DERIVED | a | ref | question_id | question_id | 4 | u.question_id | 1 | 100.00 | |
| 2 | DERIVED | s | ref | user_id,answer_choice,question_choice,score_comp_uaq | answer_choice | 5 | db_9_2522be.a.id | 1 | 100.00 | Using where |
| 3 | DERIVED | score | index | score_comp_uaq | score_comp_uaq | 14 | | 4 | 100.00 | Using index; Using temporary |
+----+-------------+-------+--------+------------------------------------------------------+----------------+---------+------------------+------+----------+----------------------------------------------+
第二个查询:
+----+-------------+---------+--------+---------------+----------------+---------+-----------------------------+------+----------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+--------+---------------+----------------+---------+-----------------------------+------+----------+-----------------------------------------------------------+
| 1 | PRIMARY | | ALL | | | | | 4 | 100.00 | |
| 1 | PRIMARY | users | eq_ref | PRIMARY | PRIMARY | 4 | s.user_id | 1 | 100.00 | |
| 1 | PRIMARY | | ref | | | 4 | s.question_id | 2 | 100.00 | |
| 3 | DERIVED | answers | index | question_id | question_id | 4 | | 19 | 100.00 | |
| 2 | DERIVED | score | index | answer_choice | score_comp_uaq | 14 | | 4 | 100.00 | Using where; Using index; Using temporary; Using filesort |
| 2 | DERIVED | answers | eq_ref | PRIMARY | PRIMARY | 4 | db_9_2522be.score.answer_id | 1 | 100.00 | |
+----+-------------+---------+--------+---------------+----------------+---------+-----------------------------+------+----------+-----------------------------------------------------------+
原始查询:
+----+-------------+---------+--------+------------------------------------------------------+----------------+---------+-------------------------------+------+----------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+--------+------------------------------------------------------+----------------+---------+-------------------------------+------+----------+-----------------------------------------------------------+
| 1 | PRIMARY | score | index | user_id,answer_choice,question_choice,score_comp_uaq | score_comp_uaq | 14 | | 4 | 100.00 | Using where; Using index; Using temporary; Using filesort |
| 1 | PRIMARY | answers | eq_ref | PRIMARY | PRIMARY | 4 | db_9_2522be.score.answer_id | 1 | 100.00 | |
| 1 | PRIMARY | | ref | | | 4 | db_9_2522be.score.user_id | 2 | 100.00 | |
| 1 | PRIMARY | | ref | | | 4 | db_9_2522be.score.question_id | 2 | 100.00 | |
| 3 | DERIVED | answers | index | question_id | question_id | 4 | | 19 | 100.00 | |
| 2 | DERIVED | users | ALL | | | | | 9 | 100.00 | |
+----+-------------+---------+--------+------------------------------------------------------+----------------+---------+-------------------------------+------+----------+-----------------------------------------------------------+