我要做的是从一张桌子上的人员列表,如果一个人不止一次存在,那么返回他们包含排名最高的“代码”的记录
代码排名(从高到低):T,E,F
因此对于给定的数据集
Person Code
----------------
Tom F
Paul E
Mark F
Paul T
Mark E
Chris T
Chris E
我会从查询中得到以下内容
Person Code
----------------
Tom F
Paul T
Mark E
Chris T
我假设这将使用排名/分析函数,但我对它们不够熟悉。
谢谢!
答案 0 :(得分:2)
您可以使用RANK
功能对数据进行排名
SQL> ed
Wrote file afiedt.buf
1 with data as (
2 select 'Tom' person, 'F' code from dual union all
3 select 'Paul', 'E' from dual union all
4 select 'Paul', 'T' from dual union all
5 select 'Mark', 'F' from dual union all
6 select 'Mark', 'E' from dual
7 )
8 select *
9 from (select person,
10 code,
11 rank() over (partition by person
12 order by (case when code='T' then 1
13 when code='E' then 2
14 when code='F' then 3
15 else null
16 end)) rnk
17* from data)
SQL> /
PERS C RNK
---- - ----------
Mark E 1
Mark F 2
Paul T 1
Paul E 2
Tom F 1
Elapsed: 00:00:00.00
然后,您只需选择RNK
为1
SQL> ed
Wrote file afiedt.buf
1 with data as (
2 select 'Tom' person, 'F' code from dual union all
3 select 'Paul', 'E' from dual union all
4 select 'Paul', 'T' from dual union all
5 select 'Mark', 'F' from dual union all
6 select 'Mark', 'E' from dual
7 )
8 select *
9 from (select person,
10 code,
11 rank() over (partition by person
12 order by (case when code='T' then 1
13 when code='E' then 2
14 when code='F' then 3
15 else null
16 end)) rnk
17 from data)
18* where rnk = 1
SQL> /
PERS C RNK
---- - ----------
Mark E 1
Paul T 1
Tom F 1
Elapsed: 00:00:00.00
答案 1 :(得分:0)
我认为RANK不是你需要的......
基本上,你的删除将如下所示:(伪查询)
delete the rows from person
where that row is not in ( select the rows from person with the highest code )
修改强>:
这个技巧也可能对你有所帮助:
select person, code, decode( code, 'T', 1, 'E', 2, 'F', 3, 0 ) from mytable
答案 2 :(得分:0)
Hum ...标准SQL的替代建议。
有一个CODE_WEIGHT
表,例如:
CODE WEIGHT
T 3
E 2
F 1
然后按Person分组查询(如果这是分组标准)并选择包含max(weight)
的不同代码。
我会在几分钟内发布查询。
<强>更新强>
好的,抱歉延误了。
这是使用前面提到的表和@Randy技巧的解决方案:
SELECT
pp.person, decode(max(c.weight), 3, 'T', 2, 'E', 1, 'F', '') code
FROM
person pp INNER JOIN code_weight c on (pp.code = c.code)
GROUP BY
pp.person
ORDER BY
person DESC;
我很确定有一种方法可以转储Oracle专有功能并在纯SQL中完成工作......无论如何,既然你已经要求提供Oracle解决方案,那么就是这样。
更新2
正如所承诺的,这是我能够提出的最好的标准SQL版本:
SELECT
p.person, c.code
FROM
(
SELECT
pp.person, MAX(cc.weight) weight
FROM
person pp INNER JOIN code_weight cc ON (pp.code = cc.code)
GROUP BY
pp.person
) p INNER JOIN code_WEIGHT c ON (p.weight = c.weight)
ORDER BY
p.person DESC;
有点丑陋的两个连接...但它没有专有扩展的工作。任何SQL大师都知道如何优化它?
干杯,
答案 3 :(得分:0)
最短,性能最高且特定于Oracle的解决方案:
SQL> create table mytable(person,code)
2 as
3 select 'Tom', 'F' from dual union all
4 select 'Paul', 'E' from dual union all
5 select 'Mark', 'F' from dual union all
6 select 'Paul', 'T' from dual union all
7 select 'Mark', 'E' from dual union all
8 select 'Chris', 'T' from dual union all
9 select 'Chris', 'E' from dual
10 /
Table created.
SQL> select person
2 , max(code) keep (dense_rank first order by decode(code,'T',1,'E',2,'F',3,4)) code
3 from mytable
4 group by person
5 /
PERSO C
----- -
Chris T
Mark E
Paul T
Tom F
4 rows selected.
的问候,
罗布。