sql的優勢之一是使用單一的命令能夠訪問到一個記錄集,其重要的特點就是非過程化。
在很多企業流行着360評分體系。比如,有A、B、C三個員工競選某要職,HR組織吃瓜羣衆位對其三位進行評分,出於不清楚的原因,HR在拿到羣衆們的評分結果後,會先對某侯選人的得分結果記錄集進行排序,再按比例去掉記錄兩頭(最高、最低)的N%評分記錄,最後再進行後續計算。
本文是直接解決以上的“去掉記錄兩頭的N%評分記錄”的問題的。最少有以下幾種方案:
(本文代碼基於SQL Server2005,關於@tb_eval表變量的定義見本文最後的附錄)
-- 去掉最高20%、最低20%評分
|
-- 去掉最高20%、最低20%評分
|
-- 去掉最高20%、最低20%評分
|
本問題其實像是大學時代的課後練習作業,寫作本文的原因主要是想說明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 |