Oracle SQL Group按列值排名

时间:2016-08-17 23:32:24

标签: sql oracle group-by rank

我最近开始在Oracle中学习数据库查询,但有一件事我在理解分组方面遇到了很多麻烦。

最好用例子来解释。假设我的源数据如下所示:

MY_SOURCE

ID | Fruit
----------
1  | Orange
1  | Apple
1  | Orange
2  | Banana
2  | Apple
3  | Apple
3  | Apple
3  | Orange

假设某些水果值具有不同的等级/优先级。说等级(1 =最重要; 3 =最不重要)是:

Fruit Rank:
1. Banana
2. Orange
3. Apple

我想按ID分组数据。当我这样做时,数据源中每个ID必须聚合的水果列将有重复项。例如,对于ID 1,可能值的集合是:

Orange, Apple, Orange

此时,我不想使用stats_mode()聚合重复的水果集,而是按水果等级对数据进行分组,只显示排名最高的值。所以,输出将是:

ID | Fruit
----------
1  | Orange
2  | Banana
3  | Orange

有没有办法在SQL中完成此操作?

我想象的查询类似于:

SELECT DISTINCT
    ID,
    MAGIC_MAX_RANK_FUNCTION(FRUIT, ['Banana','Orange', 'Apple'])
FROM
    MY_SOURCE

在技术方面,我们根据程序员为该列的所有可能值指定的排名对重复的水果数据进行分组。

提前谢谢!

1 个答案:

答案 0 :(得分:1)

我只使用GROUP BY

而不是ROW_NUMBER()
select s.*
from (select s.*,
             row_number() over (partition by id
                                order by (case fruit when 'banana' then 1 when 'orange' then 2 when 'apple' then 3 else 999 end)
                               ) as seqnum
      from my_source s
     ) s
where seqnum = 1;

另一种方法使用union all,最适合短名单:

select s.*
from my_source s
where s.fruit = 'banana'
union all
select s.*
from my_source s
where s.fruit = 'orange' and
      not exists (select 1 from my_source s2 where s2.id = s.id and s2.fruit in ('banana'))
union all
select s.*
from my_source s
where s.fruit = 'apple' and
      not exists (select 1 from my_source s2 where s2.id = s.id and s2.fruit in ('banana', 'orange'));

在某些情况下,此方法可能比之前的方法更快(反之亦然)。