做到这题时卡了不少时间,参考了别人的解法,觉得挺不错的,还挺巧妙。
SELECT s2.Score,s1.Rank From ( SELECT S1.Score, COUNT(*) as Rank FROM (SELECT DISTINCT Score from Scores) as S1, (SELECT DISTINCT Score from Scores) as S2 Where S1.Score<=S2.Score Group By S1.Score ) s1 ,Scores s2 WHERE s1.Score = s2.Score Order BY s2.Score desc
简单回顾一下题目,
+----+-------+ | Id | Score | +----+-------+ | 1 | 3.50 | | 2 | 3.65 | | 3 | 4.00 | | 4 | 3.85 | | 5 | 4.00 | | 6 | 3.65 | +----+-------+
要利用上面的表,达到
+-------+------+ | Score | Rank | +-------+------+ | 4.00 | 1 | | 4.00 | 1 | | 3.85 | 2 | | 3.65 | 3 | | 3.65 | 3 | | 3.50 | 4 | +-------+------+
这种效果,一般情况下用存储过程会比较方便地得到,但既然一句SQL可以解决,便学习一下罢。贴出的解法中的子查询起了关键作用
SELECT S1.Score, COUNT(*) as Rank FROM (SELECT DISTINCT Score from Scores) as S1, (SELECT DISTINCT Score from Scores) as S2 Where S1.Score<=S2.Score Group By S1.Score )
(该子查询的外层查询仅仅是一个连接操作然后排序,比较简明,故不赘述)
这个子查询如果单独执行,可以得到下面的结果:
可以很清楚地看到,得到了一种“排序”效果,那么为什么会得到这种效果呢,我们可以进一步拆解:
SELECT S1.Score ,Count(*)S2.Score as Rank FROM (SELECT DISTINCT Score from Scores) as S1, (SELECT DISTINCT Score from Scores) as S2 Where S1.Score<=S2.Score
这个子查询我们对其稍作修改,以便更直观地观察其结果,如果单独执行,得到如下结果:
我们可以看到,S1.Score与S2.Score进行<=操作之后,得到了这样的结果,我们知道,俩字段的比较操作,会将左边表的字段依次与右边表的字段值逐个比较,这里我们可以看到,对于左表的3.5来说,右边表有四个值满足<=的比较条件,于是,左边表的3.5会出现4次,而右边的值则是满足比较条件的值。
于是,当所有的字段比较完成之后,我们可以总结出,因为每一个字段在右边去比较的时候,总会将比其小的值筛一个出去(因为是Distinct操作,不会存在重复值),这么一来,左边表的字段的值每迭代到一个更大的值,其在结果集中出现的次数一定比上一个次小值少一次,最后将其做Group By操作,这么一来,就得到了“排序”效果。