0

我正在尝试做的是一张表格中的人员列表,如果一个人存在不止一次,则返回他们的记录,其中包含排名最高的“代码”

代码排名(从高到低):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

我假设这将使用排名/分析函数,但我对它们还不够熟悉。

谢谢!

4

4 回答 4

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

然后,您只需要选择 aRNK为 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
于 2011-09-12T22:04:40.010 回答
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
于 2011-09-12T22:00:22.327 回答
0

嗯... 标准 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 大师都知道如何优化它?

干杯,

于 2011-09-12T22:10:47.263 回答
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.

问候,
罗布。

于 2011-09-13T11:52:25.260 回答