如何在SQL Server中使用RANK()

时间:2012-10-05 03:49:41

标签: sql-server tsql

我在SQL Server中使用RANK()时遇到问题。

这是我的代码:

SELECT contendernum,
       totals, 
       RANK() OVER (PARTITION BY ContenderNum ORDER BY totals ASC) AS xRank
FROM (
   SELECT ContenderNum,
          SUM(Criteria1+Criteria2+Criteria3+Criteria4) AS totals
   FROM Cat1GroupImpersonation
   GROUP BY ContenderNum
) AS a

该查询的结果是:

contendernum    totals    xRank
          1       196        1
          2       181        1
          3       192        1
          4       181        1
          5       179        1

我想要的结果是什么:

contendernum    totals    xRank
          1       196        1
          2       181        3
          3       192        2
          4       181        3
          5       179        4

我想根据totals对结果进行排名。如果有与181相同的值,则两个数字将具有相同的xRank

8 个答案:

答案 0 :(得分:81)

变化:

RANK() OVER (PARTITION BY ContenderNum ORDER BY totals ASC) AS xRank

为:

RANK() OVER (ORDER BY totals DESC) AS xRank

看一下这个例子:

SQL Fiddle DEMO

您可能还想查看RANK (Transact-SQL)DENSE_RANK (Transact-SQL)之间的区别:

  

RANK (Transact-SQL)

     

如果两个或更多行绑定排名,则每个绑定的行都会收到相同的排   秩。例如,如果两个顶级销售人员具有相同的SalesYTD   价值,他们都排名第一。销售人员排名第二   SalesYTD排名第三,因为有两行   排名更高。因此,RANK函数并不总是返回   连续整数。

     

DENSE_RANK (Transact-SQL)

     

返回结果集分区内的行级别,而不是   排名中的任何差距。行的等级是一加上的数量   排在相关行之前的不同排名。

答案 1 :(得分:17)

要回答您的问题标题,“如何在SQL Server中使用Rank(),”这就是它的工作原理:

我将使用这组数据作为例子:

create table #tmp
(
  column1 varchar(3),
  column2 varchar(5),
  column3 datetime,
  column4 int
)

insert into #tmp values ('AAA', 'SKA', '2013-02-01 00:00:00', 10)
insert into #tmp values ('AAA', 'SKA', '2013-01-31 00:00:00', 15)
insert into #tmp values ('AAA', 'SKB', '2013-01-31 00:00:00', 20)
insert into #tmp values ('AAA', 'SKB', '2013-01-15 00:00:00', 5)
insert into #tmp values ('AAA', 'SKC', '2013-02-01 00:00:00', 25)

你有一个基本上指定分组的分区。

在此示例中,如果按column2进行分区,则rank函数将为column2值组创建排名。对于其中column2 ='SKA'的行,而不是column2 ='SKB'的行,将有不同的等级。依次类推。

排名是这样决定的: 每条记录的排名是一加上分区前面的排名数。只有当您选择的某个字段(分区字段除外)与之前的字段不同时,排名才会增加。如果所有选定的字段都相同,则排名将结合,并且两者都将被赋值为1。

知道这一点,如果我们只想从第二列中的每个组中选择一个值,我们可以使用此查询:

with cte as 
(
  select *, 
  rank() over (partition by column2 
             order by column3) rnk
  from t

) select * from cte where rnk = 1 order by column3;

结果:

COLUMN1 | COLUMN2   | COLUMN3                           |COLUMN4 | RNK
------------------------------------------------------------------------------
AAA     | SKB   | January, 15 2013 00:00:00+0000    |5   | 1
AAA     | SKA   | January, 31 2013 00:00:00+0000    |15  | 1
AAA     | SKC   | February, 01 2013 00:00:00+0000   |25  | 1

SQL DEMO

答案 2 :(得分:9)

你必须使用DENSE_RANK而不是RANK。唯一的区别是它不会留下空白。您也不应该按contender_num进行分区,否则您将每个竞争者排在一个单独的组中,因此每个竞争者在其隔离组中排名第一!

SELECT contendernum,totals, DENSE_RANK() OVER (ORDER BY totals desc) AS xRank FROM
(
SELECT ContenderNum ,SUM(Criteria1+Criteria2+Criteria3+Criteria4) AS totals
FROM dbo.Cat1GroupImpersonation
 GROUP BY ContenderNum
) AS a
order by contendernum

使用StackOverflow的提示,请发布DDL和样本数据,以便人们可以帮助您减少自己的时间!

create table Cat1GroupImpersonation (
contendernum int,
criteria1 int,
criteria2 int,
criteria3 int,
criteria4 int);

insert Cat1GroupImpersonation select
1,196,0,0,0 union all select
2,181,0,0,0 union all select
3,192,0,0,0 union all select
4,181,0,0,0 union all select
5,179,0,0,0;

答案 3 :(得分:2)

DENSE_RANK()是没有间隙的等级,即它是“密集的”。

select Name,EmailId,salary,DENSE_RANK() over(order by salary asc) from [dbo].[Employees]

RANK() - 它包含排名之间的差距。

select Name,EmailId,salary,RANK() over(order by salary asc) from [dbo].[Employees]

答案 4 :(得分:0)

您已经按照ContenderNum进行了分组,无需再次进行分区。 使用Dense_rank()并按总计desc排序。 简而言之,

SELECT contendernum,totals, **DENSE_RANK()** 
OVER (ORDER BY totals **DESC**) 
AS xRank 
FROM
(
   SELECT ContenderNum ,SUM(Criteria1+Criteria2+Criteria3+Criteria4) AS totals
   FROM dbo.Cat1GroupImpersonation
   GROUP BY ContenderNum
) AS a

答案 5 :(得分:0)

SELECT contendernum,totals, RANK() OVER (ORDER BY totals ASC) AS xRank FROM
(
SELECT ContenderNum ,SUM(Criteria1+Criteria2+Criteria3+Criteria4) AS totals
FROM dbo.Cat1GroupImpersonation
 GROUP BY ContenderNum
) AS a

答案 6 :(得分:0)

RANK()很好,但是它为相同或相似的值分配了相同的等级。而且,如果您需要唯一的排名,那么ROW_NUMBER()就可以解决此问题

ROW_NUMBER() OVER (ORDER BY totals DESC) AS xRank

答案 7 :(得分:-1)

选择T.Tamil,T.English,T.Maths,T.Total,Dense_Rank()Over(由T.Total Desc命令)为Std_Rank From(选择泰米尔语,英语,数学,(泰米尔语+英语+数学)作为学生总数)为T

enter image description here