SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较

排名函数是SQL Server2005新加的功能。在SQL Server2005中有如下四个排名函数:

  1.row_number

  2.rank

  3.dense_rank

  4.ntile  

一、row_number

  row_number函数的用途是非常广泛,这个函数的功能是为查询出来的每一行记录生成一个序号。

       其中row_number列是由row_number函数生成的序号列。在使用row_number函数是要使用over子句选择对某一列进行排序,然后才能生成序号。

二、rank

rank函数生成的序号有可能不连续

三、dense_rank

dense_rank函数的功能与rank函数类似,只是在生成序号时是连续的,而rank函数生成的序号有可能不连续。

四、ntile  

ntile函数可以对序号进行分组处理。这就相当于将查询出来的记录集放到指定长度的数组中,每一个数组元素存放一定数量的记录。ntile函数为每条记录生成的序号就是这条记录所有的数组元素的索引(从1开始)。也可以将每一个分配记录的数组元素称为“桶”。ntile函数有一个参数,用来指定桶数。


if OBJECT_ID('Test') IS NOT NULL DROP TABLE Test
go
create table Test
(
    部门 char(6),
    姓名 varchar(6),
    薪资 money
)
go
insert into Test values('市场部','张三',6000)
insert into Test values('市场部','李四',6000)
insert into Test values('市场部','王五',5000)
insert into Test values('工程部','赵柳',3400)
insert into Test values('工程部','立白',24000)
insert into Test values('工程部','雕牌',10000)
insert into Test values('策划部','海丝',2000)
insert into Test values('策划部','李波',12000)
go

--题目:找出各部门薪资最高的人

--1.常规做法:相关子查询实现

select 部门,姓名,薪资 from Test a
where 薪资=(select max(薪资) from test b where a.部门=b.部门)
/***************

=========查询结果===========

部门     姓名     薪资
------ ------ ---------------------
策划部    李波     12000.00
工程部    赵柳     24000.00
市场部    张三     6000.00

(3 行受影响)
****************/

--以上结果无法满足薪资相同的情况

------------------------------------------------------------------------

--2.常规做法:找出每个部门的最大薪资,然后子查询匹配

select test.部门,test.姓名,test.薪资 from Test,
    (select 部门,max(薪资)薪资 from test group by 部门)t 
where Test.部门=t.部门 and test.薪资=t.薪资

/*********

=========查询结果===========

部门     姓名     薪资
------ ------ ----------------
市场部    张三     6000.00
市场部    李四     6000.00
工程部    立白     24000.00
策划部    李波     12000.00

(4 行受影响)
*/
--以上结果正确
---------------------------------------------------------------------------------------------

/*
*以下的分组函数,相对Group by与 compute更好用,用得也比较多,大家可以根据实际情况,自由选择。
*下面我只是做简单介绍,有兴趣的可以看看帮助文档,或者上网查询一下。
*/
--row_number()
/*
*row_number()中的partition by就是按那个字段进行分组,并对分组后的数据进行编号
*如果没有当前字段,那么就是按排序从1开始编号。
*/

--实验
select rowid=row_number() over(order by 薪资 desc),* from Test
select rowid=row_number() over(partition by 部门 order by 薪资 desc),* from Test

/* 以上两条语句查询结果

rowid                部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    工程部    立白     24000.00
2                    策划部    李波     12000.00
3                    工程部    雕牌     10000.00
4                    市场部    张三     6000.00
5                    市场部    李四     6000.00
6                    市场部    王五     5000.00
7                    工程部    赵柳     3400.00
8                    策划部    海丝     2000.00

(8 行受影响)

rowid                部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    李波     12000.00
2                    策划部    海丝     2000.00
1                    工程部    立白     24000.00
2                    工程部    雕牌     10000.00
3                    工程部    赵柳     3400.00
1                    市场部    张三     6000.00
2                    市场部    李四     6000.00
3                    市场部    王五     5000.00

(8 行受影响)


*/

--通过以上结果我们可以通过rowid来查询,但同样无法解决薪资相同的情况

;with t as(
select rowid=row_number() over(partition by 部门 order by 薪资 desc),* from Test)
select * from t where t.rowid=1

/*结果如下:
rowid                部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    李波     12000.00
1                    工程部    立白     24000.00
1                    市场部    张三     6000.00

(3 行受影响)

*/
--以上结果也未解决同部门同薪资的情况
---------------------------------------------------------------------------
--rank()用法与row_unmber()相同

--注意下面两个查询的区别
select rankId=rank()over(order by 薪资 desc),* from Test
select rankId=rank()over(order by 部门 desc),* from Test

/* 重点看第2个结果
rankId               部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    工程部    立白     24000.00
2                    策划部    李波     12000.00
3                    工程部    雕牌     10000.00
4                    市场部    张三     6000.00
4                    市场部    李四     6000.00
6                    市场部    王五     5000.00
7                    工程部    赵柳     3400.00
8                    策划部    海丝     2000.00

(8 行受影响)

rankId               部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    市场部    张三     6000.00
1                    市场部    李四     6000.00
1                    市场部    王五     5000.00
4                    工程部    赵柳     3400.00
4                    工程部    立白     24000.00
4                    工程部    雕牌     10000.00
7                    策划部    海丝     2000.00
7                    策划部    李波     12000.00

(8 行受影响)

*/
--rank() 即是不连续编号的分组函数
select rankId=rank() over(partition by 部门 order by 薪资 desc),* from Test

/* 查询结果
rankId               部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    李波     12000.00
2                    策划部    海丝     2000.00
1                    工程部    立白     24000.00
2                    工程部    雕牌     10000.00
3                    工程部    赵柳     3400.00
1                    市场部    张三     6000.00
1                    市场部    李四     6000.00
3                    市场部    王五     5000.00

(8 行受影响)


--此处需要注意的是,如果同部门同薪资,他们的编号相同,
--比如这里两个薪资为6000的行他们的编号都是“1”,而5000的这一行是“3”而不是“2”。
*/

--通过以上结果很明确的可以知道我们的结果就出来了(能够完美解决相同问题)

;with t as(
    select rankId=rank() over(partition by 部门 order by 薪资 desc),* from Test)
select * from t where t.rankid=1

/* 查询结果
rankId               部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    李波     12000.00
1                    工程部    立白     24000.00
1                    市场部    张三     6000.00
1                    市场部    李四     6000.00

(4 行受影响)
*/

--dense_rank()与rank()相反,即他的编号是连续的,可以自己对比一下他们的区别
select drankId=dense_rank()over(order by 薪资),* from Test
select drankId=dense_rank()over(order by 部门),* from Test

/*
drankId              部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    海丝     2000.00
2                    工程部    赵柳     3400.00
3                    市场部    王五     5000.00
4                    市场部    张三     6000.00
4                    市场部    李四     6000.00
5                    工程部    雕牌     10000.00
6                    策划部    李波     12000.00
7                    工程部    立白     24000.00

(8 行受影响)

drankId              部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    海丝     2000.00
1                    策划部    李波     12000.00
2                    工程部    赵柳     3400.00
2                    工程部    立白     24000.00
2                    工程部    雕牌     10000.00
3                    市场部    张三     6000.00
3                    市场部    李四     6000.00
3                    市场部    王五     5000.00

(8 行受影响)

*/
 

;with t as(
    select drankId=dense_rank() over(partition by 部门 order by 薪资 desc),* from Test)
select * from t where drankid=1

/*
drankId              部门     姓名     薪资
-------------------- ------ ------ ---------------------
1                    策划部    李波     12000.00
1                    工程部    立白     24000.00
1                    市场部    张三     6000.00
1                    市场部    李四     6000.00

(4 行受影响)

*/

--顺便介绍一下ntile() 分组函数,平均分配
--ntile()
select tileid=ntile(6) over(order by 部门),* from Test



转自:

http://topic.csdn.net/u/20120731/10/32331a56-b060-4b01-9fe4-8f20f6e3cd18.html?seed=1803686804&r=79277841#r_79277841

http://www.cnblogs.com/xhyang110/archive/2009/10/27/1590448.html


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是这些分析函数SQL中的语法和实例: 1. DENSE_RANK函数语法:DENSE_RANK() OVER (ORDER BY column_name) DENSE_RANK函数可以用来计算某一列的密集排名,即相等值的数据行将得到相同的排名,但是排名之间没有间隔。 示例: 假设我们有一个名为“customers”的表,其中包含客户名称和订单总数。我们可以使用DENSE_RANK函数来按订单总数对客户进行排名,如下所示: SELECT customer_name, order_total, DENSE_RANK() OVER (ORDER BY order_total DESC) as dense_rank FROM customers; 结果将返回客户名称、订单总数和密集排名,按订单总数降序排序。 2. NTILE函数语法:NTILE(n) OVER (ORDER BY column_name) NTILE函数可以将一列数据分成n个等份,并返回每个数据所在的组号。 示例: 假设我们有一个名为“students”的表,其中包含学生姓名和成绩。我们可以使用NTILE函数将学生按成绩分成3组,并返回每个学生所在的组号,如下所示: SELECT student_name, grade, NTILE(3) OVER (ORDER BY grade DESC) as ntile FROM students; 结果将返回学生姓名、成绩和组号,按成绩降序排序并分成3组。 3. RANK函数语法:RANK() OVER (ORDER BY column_name) RANK函数可以用来计算某一列的排名,相等值的数据行将得到相同的排名,并且排名之间会有间隔。 示例: 假设我们有一个名为“employees”的表,其中包含员工姓名和销售额。我们可以使用RANK函数来按销售额对员工进行排名,如下所示: SELECT employee_name, sales, RANK() OVER (ORDER BY sales DESC) as rank FROM employees; 结果将返回员工姓名、销售额和排名,按销售额降序排序。 4. ROW_NUMBER函数语法:ROW_NUMBER() OVER (ORDER BY column_name) ROW_NUMBER函数可以用来给每一行数据分配一个唯一的数字标识,不考虑数据是否相等。 示例: 假设我们有一个名为“orders”的表,其中包含订单号、客户名称和订单总数。我们可以使用ROW_NUMBER函数来对订单进行编号,并按订单总数降序排序,如下所示: SELECT order_number, customer_name, order_total, ROW_NUMBER() OVER (ORDER BY order_total DESC) as row_number FROM orders; 结果将返回订单号、客户名称、订单总数和行号,按订单总数降序排序并为每个订单分配一个唯一的行号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值