sql实现在评分记录集中去掉最高、最低百分之N评分记录

sql的优势之一是使用单一的命令能够访问到一个记录集,其重要的特点就是非过程化。

        在很多企业流行着360评分体系。比如,有A、B、C三个员工竞选某要职,HR组织吃瓜群众位对其三位进行评分,出于不清楚的原因,HR在拿到群众们的评分结果后,会先对某侯选人的得分结果记录集进行排序,再按比例去掉记录两头(最高、最低)的N%评分记录,最后再进行后续计算。

        本文是直接解决以上的“去掉记录两头的N%评分记录”的问题的。最少有以下几种方案:

      (本文代码基于SQL Server2005,关于@tb_eval表变量的定义见本文最后的附录)

-- 去掉最高20%、最低20%评分

select *
from
@tb_eval a01
where a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score desc)
and a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score asc)
order by empid, score desc

 

-- 去掉最高20%、最低20%评分

select * 
from 
(
	select row_number() over (partition by empid order by score desc) rowno, *
	from @tb_eval
) a01
where rowno > (select cast(round(count(*)*0.2,0) as int) padcnt from @tb_eval a02 where a01.empid=a02.empid)
and rowno <= (select (count(*) - cast(round(count(*)*0.2,0) as int)) padcnt from @tb_eval a02 where a01.empid=a02.empid)

 

-- 去掉最高20%、最低20%评分

select a01.*
from 
(
	select row_number() over (partition by empid order by score desc) rowno, *
	from @tb_eval
) a01
left join 
(
	select empid, cast(round(count(*)*0.2,0) as int) topcnt, cast(round(count(*)*0.2,0) as int) lastcnt, count(*) as totalcnt 
	from @tb_eval 
	group by empid
) a02
on a01.empid=a02.empid
where a01.rowno>a02.topcnt and a01.rowno <= (a02.totalcnt - a02. lastcnt)

  

本问题其实像是大学时代的课后练习作业,写作本文的原因主要是想说明sql的非过程化,你不应该使用游标去完成本任务。

 附录:

1、完整的代码

-- 人员表(本例不使用)
declare @tb_emp table table
(
    id    int,				-- 人员ID
    name    varchar(64)		-- 人员名称
);

insert into @tb_emp (id, name) values(1, 'emp01');
insert into @tb_emp (id, name) values(2, 'emp02');
insert into @tb_emp (id, name) values(3, 'emp03');
insert into @tb_emp (id, name) values(4, 'emp04');
insert into @tb_emp (id, name) values(5, 'emp05');
insert into @tb_emp (id, name) values(6, 'emp06');
insert into @tb_emp (id, name) values(7, 'emp07');
insert into @tb_emp (id, name) values(8, 'emp08');
insert into @tb_emp (id, name) values(9, 'emp09');
insert into @tb_emp (id, name) values(10, 'emp10');
insert into @tb_emp (id, name) values(11, 'emp11');
insert into @tb_emp (id, name) values(12, 'emp12');
insert into @tb_emp (id, name) values(13, 'emp13');
insert into @tb_emp (id, name) values(14, 'emp14');
insert into @tb_emp (id, name) values(15, 'emp15');
insert into @tb_emp (id, name) values(16, 'emp16');
insert into @tb_emp (id, name) values(17, 'emp17');
insert into @tb_emp (id, name) values(18, 'emp18');
insert into @tb_emp (id, name) values(19, 'emp19');
insert into @tb_emp (id, name) values(20, 'emp20');
insert into @tb_emp (id, name) values(21, 'emp21');
insert into @tb_emp (id, name) values(22, 'emp22');
insert into @tb_emp (id, name) values(23, 'emp23');
insert into @tb_emp (id, name) values(24, 'emp24');
insert into @tb_emp (id, name) values(25, 'emp25');


-- 评分表
declare @tb_eval table
(
	    id	int not null identity(1,1) primary key,		-- 评分表自动编号
	    empid int,						-- 被评分人员ID
	    score decimal(10, 2),				-- 评分
            examinerid int					-- 评分人员ID
);

-- 给empid为1, 3, 5的评分
insert into @tb_eval (empid, score, examinerid) values (1,9, 4);
insert into @tb_eval (empid, score, examinerid) values (1,76, 19);
insert into @tb_eval (empid, score, examinerid) values (1,37, 10);
insert into @tb_eval (empid, score, examinerid) values (1,90, 13);
insert into @tb_eval (empid, score, examinerid) values (1,29, 7);
insert into @tb_eval (empid, score, examinerid) values (1,6, 2);
insert into @tb_eval (empid, score, examinerid) values (1,69, 17);
insert into @tb_eval (empid, score, examinerid) values (1,76, 5);
insert into @tb_eval (empid, score, examinerid) values (1,60, 15);
insert into @tb_eval (empid, score, examinerid) values (3,13, 20);
insert into @tb_eval (empid, score, examinerid) values (3,49, 6);
insert into @tb_eval (empid, score, examinerid) values (3,72, 25);
insert into @tb_eval (empid, score, examinerid) values (3,84, 2);
insert into @tb_eval (empid, score, examinerid) values (3,4, 22);
insert into @tb_eval (empid, score, examinerid) values (3,17, 11);
insert into @tb_eval (empid, score, examinerid) values (3,74, 18);
insert into @tb_eval (empid, score, examinerid) values (3,66, 21);
insert into @tb_eval (empid, score, examinerid) values (3,62, 8);
insert into @tb_eval (empid, score, examinerid) values (3,4, 4);
insert into @tb_eval (empid, score, examinerid) values (3,66, 13);
insert into @tb_eval (empid, score, examinerid) values (3,41, 3);
insert into @tb_eval (empid, score, examinerid) values (3,94, 16);
insert into @tb_eval (empid, score, examinerid) values (5,87, 24);
insert into @tb_eval (empid, score, examinerid) values (5,71, 14);
insert into @tb_eval (empid, score, examinerid) values (5,39, 22);
insert into @tb_eval (empid, score, examinerid) values (5,55, 12);
insert into @tb_eval (empid, score, examinerid) values (5,13, 19);
insert into @tb_eval (empid, score, examinerid) values (5,73, 16);
insert into @tb_eval (empid, score, examinerid) values (5,45, 10);
insert into @tb_eval (empid, score, examinerid) values (5,9, 15);
insert into @tb_eval (empid, score, examinerid) values (5,4, 8);
insert into @tb_eval (empid, score, examinerid) values (5,31, 11);

-- 全部评分按empid分组后,每组从高到低评分
select row_number() over (partition by empid order by score desc) rowno, * 
from @tb_eval

-- 去掉最高20%、最低20%评分
select *
from 
@tb_eval a01 
where a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score desc) 
and a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score asc) 
order by empid, score desc 

-- 去掉最高20%、最低20%评分
select a01.*
from 
(
	select row_number() over (partition by empid order by score desc) rowno, * 
	from @tb_eval 
) a01 
left join 
(
	select empid, cast(round(count(*)*0.2,0) as int) topcnt, cast(round(count(*)*0.2,0) as int) endcnt, count(*) as totalcnt 
	from @tb_eval 
	group by empid 
) a02 
on a01.empid=a02.empid 
where a01.rowno>a02.topcnt and a01.rowno <= (a02.totalcnt - a02.endcnt) 

-- 去掉最高20%、最低20%评分
select * 
from 
( 
	select row_number() over (partition by empid order by score desc) rowno, * 
	from @tb_eval 
) a01 
where rowno > (select cast(round(count(*)*0.2,0) as int) padcnt from @tb_eval a02 where a01.empid=a02.empid) 
and rowno <= (select (count(*) - cast(round(count(*)*0.2,0) as int)) padcnt from @tb_eval a02 where a01.empid=a02.empid) 


2、未进行去头、去尾的结果: 

rowno

id

empid

score

examinerid

1

4

1

90

13

2

2

1

76

19

3

8

1

76

5

4

7

1

69

17

5

9

1

60

15

6

3

1

37

10

7

5

1

29

7

8

1

1

9

4

9

6

1

6

2

1

22

3

94

16

2

13

3

84

2

3

16

3

74

18

4

12

3

72

25

5

17

3

66

21

6

20

3

66

13

7

18

3

62

8

8

11

3

49

6

9

21

3

41

3

10

15

3

17

11

11

10

3

13

20

12

14

3

4

22

13

19

3

4

4

1

23

5

87

24

2

28

5

73

16

3

24

5

71

14

4

26

5

55

12

5

29

5

45

10

6

25

5

39

22

7

32

5

31

11

8

27

5

13

19

9

30

5

9

15

10

31

5

4

8


3、去头、去尾后的结果:

rowno

id

empid

score

examinerid

3

8

1

76

5

4

7

1

69

17

5

9

1

60

15

6

3

1

37

10

7

5

1

29

7

4

12

3

72

25

5

17

3

66

21

6

20

3

66

13

7

18

3

62

8

8

11

3

49

6

9

21

3

41

3

10

15

3

17

11

3

24

5

71

14

4

26

5

55

12

5

29

5

45

10

6

25

5

39

22

7

32

5

31

11

8

27

5

13

19




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值