我有一个名为'allscores'的大型SQL表,类似于以下内容:
user score quiz_id high_score
Bob 90 math 1
John 80 math 0
John 85 math 1
Steve 100 math 1
Bob 95 reading 0
Bob 100 reading 1
John 80 reading 1
'high_score'字段在表中开头,并且对于该测验的用户得分最高的行,总是设置为'1'。
我想要的是一个SQL查询,我可以在单个用户上运行以从两个测验(“数学”和“阅读”)中的每一个中获得最高分,以及他们在该测验的分数中的总体排名。到目前为止我所拥有的是:
SELECT `user`, `score`, `quiz_id` FROM `allscores` WHERE `user`="Bob" AND `high_score`="1"
将输出以下内容:
user score quiz_id
Bob 90 math
Bob 100 reading
此查询只是从每个测验中提取Bob的最高分 - 我想要添加的是该特定测验中分数的分数排名 - 所以输出如下:
user score quiz_id rank
Bob 90 math 2
Bob 100 reading 1
由于史蒂夫得分较高,鲍勃的数学测验排名为'2',但由于得分最高,因此他的阅读排名为“1”。
如何将此排名列添加到现有查询?
答案 0 :(得分:2)
这使用MS T-SQL语法,但如果您的SQL风格使用窗口函数,它应该是类似的。
MS SQL Server 2017架构设置:
CREATE TABLE t (
[user] varchar(10)
, score int
, quiz_id varchar(10)
, high_score bit
) ;
INSERT INTO t ([user], score, quiz_id, high_score)
VALUES
( 'Bob',90,'math',1 )
, ( 'John',80,'math',0 )
, ( 'Steve',100,'math',1 )
, ( 'Bob',95,'reading',0 )
, ( 'Bob',100,'reading',1 )
, ( 'John',85,'math',1 )
, ( 'John',80,'reading',1 )
;
MAIN QUERY :
SELECT s1.[user]
, s1.score
, s1.quiz_id
, s1.high_score
--, s1.isUserHighScore
, s1.ranking
FROM (
SELECT
t.[user]
, t.score
, t.quiz_id
, t.high_score
--, ROW_NUMBER() OVER (PARTITION BY t.[user],t.quiz_id ORDER BY t.score DESC) AS isUserHighScore
, DENSE_RANK() OVER (PARTITION BY t.quiz_id ORDER BY t.score DESC ) AS ranking
FROM t
) s1
WHERE s1.[user]='Bob'
--AND s1.isUserHighScore = 1
AND s1.high_score = 1
<强> Results 强>:
| user | score | quiz_id | high_score | isUserHighScore | ranking |
|------|-------|---------|------------|-----------------|---------|
| Bob | 90 | math | true | 1 | 2 |
| Bob | 100 | reading | true | 1 | 1 |
我使用ROW_NUMBER()
来确定用户测验中的最高分数,然后使用DENSE_RANK()
计算用户分数与其他分数的排名。 DENSE_RANK()
和RANK()
之间的差异基本上是DENSE_RANK()
不会在排名中留下任何空白。例如:2人得分为90,1得分为80,然后得到DENSE_RANK()
,90s都是Rank 1,80则是Rank 2.使用RANK()
,90s将是Rank 1和80将是Rank 3.