sql實現在評分記錄集中去掉最高、最低百分之N評分記錄

版權聲明:本文爲博主原創文章,但是你也可以隨意轉載。 https://blog.csdn.net/smartcore/article/details/79051420

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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章