mysql - FIND_IN_SET 与 GROUP_CONCAT 太慢(MySQL 中的密集排名)

标签 mysql sql

我有一个查询,根据列的值计算密集排名:

SELECT id,
       score1, 
       FIND_IN_SET
       ( 
         score1, 
          ( 
            SELECT GROUP_CONCAT(score1  ORDER BY score1  DESC) FROM scores 
          ) 
       ) as rank 
FROM score_news;

这是查询结果的样子:

+----+--------+------+
| id | score1 | rank |
+----+--------+------+
|  1 |     15 |    1 |
|  2 |     15 |    1 |
|  3 |     14 |    3 |
|  4 |     13 |    4 |
+----+--------+------+

当分数数量增加N倍时,查询将花费Nx的时间。有什么办法可以优化这个吗?我的 table 大小约为 106

注意:我已经尝试过使用 mysql 用户变量的技术,但是当我在大型集合上运行它时,我得到了不一致的结果。经过调查,我在 MySQL 文档中发现了这一点:

The order of evaluation for user variables is undefined and may change based on the elements contained within a given query. In SELECT @a, @a := @a+1 ..., you might think that MySQL will evaluate @a first and then do an assignment second, but changing the query (for example, by adding a GROUP BY, HAVING, or ORDER BY clause) may change the order of evaluation...The general rule is never to assign a value to a user variable in one part of a statement and use the same variable in some other part of the same statement. You might get the results you expect, but this is not guaranteed.

我对用户变量的尝试:

SELECT
      a.id,
      @prev := @curr as prev,
      @curr := a.score1 as curr,
      @rank := IF(@rank = 0, @rank + 1, IF(@prev > @curr, @rank+@ties, @rank)) AS rank,
      @ties := IF(@prev = @curr, @ties+1, 1) AS ties
    FROM
      scores a,
      (
        SELECT
          @curr := null,
          @prev := null,
          @rank := 0,
          @ties := 1,
          @total := count(*) 
        FROM scores 
        WHERE score1 is not null 
      ) b
    WHERE
      score1 is not null 
    ORDER BY
      score1 DESC
   ) 

最佳答案

使用变量的解决方案可以工作,但您需要首先对结果集进行排序,然后才然后处理变量分配:

SELECT a.id,
       @rank := IF(@curr = a.score1, @rank, @rank + @ties) AS rank,
       @ties := IF(@curr = a.score1, @ties + 1, 1) AS ties,
       @curr := a.score1 AS curr
FROM   (SELECT * FROM scores WHERE score1 is NOT NULL ORDER BY score1 DESC) a,
       (SELECT @curr := null, @rank := 0, @ties := 1) b

注意:我将 curr 列放在 select 子句的最后以保存一个变量。

关于mysql - FIND_IN_SET 与 GROUP_CONCAT 太慢(MySQL 中的密集排名),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47468262/

相关文章:

Java MySQL 连接池不工作

mysql - 选择多对多表中仅具有一个映射的列

SQL Left Join加倍汇总列的值

sql - SQL选择一行并存储在SQL变量中

mysql - 在 MySQL 中使用登录时间戳统计活跃用户

sql - 如何在 SSIS 中截断多个表(使用 ADO.NET 目标和 Oracle 数据库)

jquery - 使用jsp、servlet将图像上传到mysql

mysql - 更新 (SELECT ....) 列表中的用户

PHP将日期插入mysql数据库

mysql - 使用nodejs和数据库存储GPS纬度和经度的最佳方式