假设我有一个这样的字符表:
(我之所以使用游戏统计信息,只是因为它更易于理解)

id    age  strength intelligence speed
 1    int    int       int        int
 2    int    int       int        int
 3    int    int       int        int
 4    int    int       int        int
 5    int    int       int        int
 6    int    int       int        int
 7    int    int       int        int
...   ...    ...       ...        ...
999   int    int       int        int


如何编写MySQL查询来查找30岁以下所有在强度上排在前50位,在智力上排在前50位,在速度上排在前50位的字符?

棘手的部分是此查询将不会被硬编码,它将由前端的代码构造,并且所有条件都是动态的,因此我想拥有一个扁平且可扩展的查询,更好地避免了许多嵌套的JOINS x.id = y.id = z.id的部分在每个JOIN中都会更改,这很难编写。

我已经花了很多时间阅读文档,但是却做得不好。我尝试了WHERE id IN,但是MySQL在这种情况下不支持它。我也读过关于EXISTS的文章,但是文档说它的性能确实很差。

最佳答案

该规范并不清楚“排名前50位”的含义。

假设这意味着按照strength的顺序获取所有行的前50行,并丢弃/排除其余行...

我建议使用一系列内联视图来分别获取五十个id值,并加入这些集合以获取交集...

 SELECT t.id
      , t.age
      , t.strength
      , t.intelligence
      , t.strength
   FROM ( SELECT qq.id
            FROM mytable qq
           ORDER BY qq.strength DESC
           LIMIT 50
        ) q
   JOIN ( SELECT rr.id
            FROM mytable rr
           ORDER BY rr.intelligence DESC
           LIMIT 50
        ) r
     ON r.id = q.id
   JOIN ( SELECT ss.id
            FROM mytable ss
           ORDER BY ss.speed DESC
           LIMIT 50
        ) s
     ON s.id = q.id
   JOIN mytable t
     ON t.id = q.id
  WHERE t.age < 30
  ORDER BY ...


为了获得最佳性能,我们需要适当的索引,以避免昂贵的“使用文件排序”操作,例如

... ON mytable (strength, ...)
... ON mytable (intelligence, ...)
... ON mytable (speed, ...)


假设有一个合适的索引,以id作为前导列,例如如果是InnoDB,则id列是PRIMARY KEY(集群索引)。使用EXPLAIN查看执行计划。

关于mysql - 在列1和列2以及列3中找到前50名内排名最高的所有行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49594613/

10-11 17:25