我有一个关于sql的问题。我有一个问题,看起来像这样。
+----+-------+
| 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 |
+-------+------+
这是一个示例答案,但我对WHERE之后的部分感到困惑。
select
s.Score,
(select count(distinct Score) from Scores where Score >= s.Score)
Rank
from Scores s
order by s.Score Desc;
这个分数> = s.Score就像分数列与自身比较。我完全对这部分感到困惑。它是如何工作的?谢谢!
E.
这称为从属子查询(并且可能非常低效)。依赖子查询 - 基本上意味着它不能转换为连接,因为它“依赖于”特定值 - 为输出中的每个结果行运行特定的“依赖”值。在这种情况下,每个结果行已经具有s.Score
的“特定”值。
从属子查询中的“得分”是指原始表而不是外部查询。
另外一个别名可能更清楚:
select
s.Score,
(select count(distinct other_scores.Score)
from Scores other_scores
where other_scores.Score >= s.Score) Rank -- value of s.Score is known
-- and placed directly into dependent subquery
from Scores s
order by s.Score Desc;
“现代”SQL方言(包括MySQL 8.0+)提供“RANK”和“DENSE_RANK”窗口函数来回答这些类型的查询。窗口函数(如果适用)通常比依赖查询快得多,因为查询规划器可以在更高级别进行优化:这些函数也倾向于驯服其他粗略的SQL。
MySQL 8+ SQL语法应该做的伎俩:
select
s.Score,
DENSE_RANK() over w AS Rank
from Scores s
window w as (order by Score desc)
对于旧版本的MySQL,还有various work-abouts to emulate ROW_NUMBER / Window Functions。
理解这一点的一种方法是只为示例数据的每一行运行查询。从第一行开始,我们看到得分是4.00
。 select子句中的相关子查询:
(select count(distinct Score) from Scores where Score >= s.Score)
将返回1的计数,因为只有一个记录的独特分数大于或等于4.00
。数据中的第二条记录也是如此,其得分也为4.00
。对于得分3.85
,子查询将找到2的明显计数,因为有两个得分大于或等于3.85
,即3.85
和4.00
。您可以在整个表中应用此逻辑,以说服自己查询的工作方式。
+-------+------+
| Score | Rank |
+-------+------+
| 4.00 | 1 | <-- 1 score >= 4.00
| 4.00 | 1 | <-- 1 score >= 4.00
| 3.85 | 2 | <-- 2 scores >= 3.85
| 3.65 | 3 | <-- 3 scores >= 3.65
| 3.65 | 3 | <-- 3 scores >= 3.65
| 3.50 | 4 | <-- 4 scores >= 3.50
+-------+------+