通过两次不使用/查询相同的表来优化mysql查询

时间:2017-11-28 20:20:29

标签: mysql database

感谢您帮助我优化以下查询的客气话和智慧,因为我想使用"答案"表只有一次。同样,如果附带任何解释,我会很高兴。

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
; 

1 个答案:

答案 0 :(得分:0)

注意所有查询(包括您的原始查询)都是通过在得分表上添加复合索引来改进的,如下所示:

ALTER TABLE `score` ADD INDEX `score_comp_uaq` (`user_id`, `answer_id`, `question_id`);

您的最终得分公式是指两种不同背景下的答案:

  1. 可能的答案,
  2. 实际答案
  3. 因此,避免两次使用答案表的一种方法是使用外部联接,这样我们就可以在一次访问中同时访问可能的和实际的。然而,在这种方法中,存在一个问题,即知道用户尝试了哪些问题,同时减少了答案表上的传递,它需要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 |                                                           |
    +----+-------------+---------+--------+------------------------------------------------------+----------------+---------+-------------------------------+------+----------+-----------------------------------------------------------+