【问题标题】:Return Rank In SQL Query Based On Multiple Columns基于多列的 SQL 查询中的返回排名
【发布时间】:2018-07-11 01:22:52
【问题描述】:

我有一个名为“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

Bob 的数学测验排名为“2”,因为 Steve 的分数较高,但他的阅读排名为“1”,因为他的分数最高。

如何将此排名列添加到我现有的查询中?

【问题讨论】:

  • 什么版本和类型的 SQL?
  • 而在排名时,你如何处理平局?

标签: sql phpmyadmin


【解决方案1】:

这使用 MS T-SQL 语法,但如果你的 SQL 风格使用窗口函数,它应该是类似的。

SQL Fiddle

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 )
;

主要查询

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() 中,90 年代将成为 1 级,80 年代将成为 2 级。RANK() 时,90 年代将成为 1 级,80 后将成为 Rank 3.

【讨论】:

  • 抱歉,刚刚发现我的isUserHighScore 和你的high_score 本质上是一回事。我第一次看错了,以为你的high_score指的是测验的最高分。
  • 注释掉我额外的isUserHighScore 计算。
  • sqlfiddle.com/#!18/8a62c/1 DENSE_RANK() 和 RANK() 返回的差异。
  • 实际上我需要 MySQL 5.6 代码 - 我试过这个但不能在 phpmyadmin 中使用,因为 RANK() 函数不是 MySQL 5.6 的一部分
  • 希望使用与 RANK() 相同的方法处理平局 - 即它们获得相同的排名号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
相关资源
最近更新 更多