0

所以我在这样的表中有数据:

id        total   group_id
1897      738      1
2489      716      2
2325      715      3
1788      702      2
1707      699      3
2400      688      3
2668      682      2
1373      666      1
1494      666      1
1564      660      1
2699      659      1
1307      648      4
1720      645      4
2176      644      1
1454      644      4
2385      639      3
1001      634      2
2099      634      4
1006      632      1
2587      630      3
1955      624      3
1827      624      4
2505      623      4
2062      621      3
1003      618      1
2286      615      4
2722      609      4

我如何根据总数对每组的 id 进行排名,并在出现平局时给予相同的排名?

我在下面尝试了这个解决方案,但它没有处理关系。

SELECT g1.admission_no
 , g1.total
 , g1.stream_id
 , COUNT(*) AS rn
 FROM ranktest   AS g1
   JOIN ranktest   AS g2
   ON (g2.total, g2.admission_no) >= (g1.total, g1.admission_no)
   AND g1.stream_id = g2.stream_id
   GROUP BY g1.admission_no
    , g1.stream_id
    , g1.total
   ORDER BY g1.stream_id
    , total ;

预期的

id        total   group_id rank
1897      738      1        1
2489      716      2        1
2325      715      3        1
1788      702      2        2 
1707      699      3        2
2400      688      3        3
2668      682      2        3
1373      666      1        2
1494      666      1        2
1564      660      1        3
2699      659      1        4
1307      648      4        1
1720      645      4        2
2176      644      1        4
1454      644      4        3
2385      639      3        4
1001      634      2        4
2099      634      4        4
1006      632      1        5
2587      630      3        5
1955      624      3        6
1827      624      4        5
2505      623      4        6
2062      621      3        6
1003      618      1        6
2286      615      4        7 
2722      609      4        8 
4

3 回答 3

2

如果原始订单不是很重要,您可以从:

http://sqlfiddle.com/#!9/a15a2/10

SELECT
    ranktest.*,
    IF(@rank IS NULL,@rank:=1, IF(@prev!=group_id,@rank:=1,@rank:=@rank+1) ) rank,
     @prev:=group_id
FROM ranktest
ORDER BY group_id, total

但请记住,从性能角度来看,这不是非常有效的查询。

于 2016-07-22T16:15:13.420 回答
1

来自题为User-Defined Variables的 MySQL 手册页:

在下面的语句中,您可能认为 MySQL 会先评估 @a,然后再进行赋值:

SELECT @a, @a:=@a+1, ...;

但是,涉及用户变量的表达式的求值顺序是未定义的。

这就是为什么很少有人能正确、安全地写出这些答案。我们的目标不是一次达到预期的结果,而是使用最佳实践和有保证的结果在现实环境中一次又一次地做到这一点。

如果您不阅读强制性文档并实施它,则无法保证您的结果。没有偷懒的方法可以做到这一点,甚至不应该打扰:p

select id,total,group_id,rank 
from 
(   select id,total,group_id, 
    @rn:=if(  group_id!=@curr_grp, greatest(@grp_rank:=1,0), 
        if(total=@prev_grp_total,@grp_rank,greatest(@grp_rank:=@grp_rank+1,0) ) ) as rank, 
    @curr_grp:=group_id, 
    @prev_grp_total:=total 
    from trans01 
    cross join (select @grp_rank:=0,@curr_grp:=0,@prev_grp_total:=-1) xParams 
    order by group_id,total desc 
)xDerived; 

+------+-------+----------+------+
| id   | total | group_id | rank |
+------+-------+----------+------+
| 1897 |   738 |        1 | 1    |
| 1373 |   666 |        1 | 2    |
| 1494 |   666 |        1 | 2    |
| 1564 |   660 |        1 | 3    |
| 2699 |   659 |        1 | 4    |
| 2176 |   644 |        1 | 5    |
| 1006 |   632 |        1 | 6    |
| 1003 |   618 |        1 | 7    |

| 2489 |   716 |        2 | 1    |
| 1788 |   702 |        2 | 2    |
| 2668 |   682 |        2 | 3    |
| 1001 |   634 |        2 | 4    |

| 2325 |   715 |        3 | 1    |
| 1707 |   699 |        3 | 2    |
| 2400 |   688 |        3 | 3    |
| 2385 |   639 |        3 | 4    |
| 2587 |   630 |        3 | 5    |
| 1955 |   624 |        3 | 6    |
| 2062 |   621 |        3 | 7    |

| 1307 |   648 |        4 | 1    |
| 1720 |   645 |        4 | 2    |
| 1454 |   644 |        4 | 3    |
| 2099 |   634 |        4 | 4    |
| 1827 |   624 |        4 | 5    |
| 2505 |   623 |        4 | 6    |
| 2286 |   615 |        4 | 7    |
| 2722 |   609 |        4 | 8    |
+------+-------+----------+------+
于 2016-07-22T16:18:42.013 回答
0

在谷歌搜索后想出了这个答案..不确定它是最好的,但它适用于我的情况:

 SELECT id, group_id, total,
   @std:=CASE WHEN @grp <> group_id THEN  concat(left(@grp:=group_id, 0), 1) ELSE if(@prev=total,@std,@std+1) END AS rn,@prev:=total 
FROM
    (SELECT @std:= -1) s,
 (SELECT @grp:= -1,@prev:=null) c,
 (SELECT *
  FROM table
  ORDER BY group_id, total desc
) s
于 2016-07-22T16:12:51.480 回答