Mysql 在别名上使用 order by 时响应时间过长

Mysql taking too long time to respond when using order by on alias

我正在尝试根据用户 ID 对来自两个不同 table 的两个字段求和。这是我的查询

SELECT
    users.id,
    users.`name`,
    users.`type`,
((SELECT IFNULL(SUM(answers.points),0) FROM answers WHERE answers.answered_by=users.id)
+
(SELECT IFNULL(SUM(points.point),0) FROM points WHERE points.user_id=users.id)) points 
FROM
    users
WHERE
    users.type = '3' GROUP BY users.id ORDER BY points DESC LIMIT 0,100;

当我删除 ORDER BY 点数据时,正在快速获取数据。但是使用 ORDER BY points 花费了将近 5 分钟的时间。有时会返回连接丢失消息。

有人可以帮忙吗?真的在为这个问题苦苦挣扎

正如 Progman 所要求的,这里是使用 ORDER BY

的 EXPLAIN
id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY users   ALL PRIMARY             18396   Using where; Using temporary; Using filesort
3   DEPENDENT SUBQUERY  points  ALL                 39  Using where
2   DEPENDENT SUBQUERY  answers ALL                 240347  Using where

没有 ORDER BY

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY users   index   PRIMARY PRIMARY 4       100 Using where
3   DEPENDENT SUBQUERY  points  ALL                 39  Using where
2   DEPENDENT SUBQUERY  answers ALL                 240347  Using where

我可以建议下一个查询:

SELECT
    users.id,
    users.`name`,
    users.`type`,
    (
        IFNULL(SUM(answers.points),0) + 
        IFNULL(SUM(points.point),0)
    ) points 
FROM users
LEFT JOIN answers ON answers.answered_by=users.id
LEFT JOIN points ON points.user_id=users.id
WHERE
    users.type = 3 
GROUP BY users.id 
ORDER BY points 
DESC LIMIT 0,100;

使用 JOIN 应该比子查询更有效

此处子查询在避免重复方面表现更好

-- MySQL
SELECT u.id
     , u.name
     , u.type
     , COALESCE(p.points, 0) points
FROM users u
LEFT JOIN (SELECT t.user_id, SUM(points) points
           FROM ( SELECT answered_by AS user_id, points
                  FROM answers

                  UNION ALL

                  SELECT user_id, point AS points
                  FROM points ) t
           GROUP BY t.user_id ) p
      ON u.id = p.user_id
WHERE u.type = '3'
ORDER BY p.points DESC LIMIT 0, 100;