Oracle相当于Postgres的DISTINCT ON?

时间:2012-05-09 11:44:57

标签: sql oracle postgresql

在postgres中,您可以使用DISTINCT ON查询组中的第一个值。 如何在Oracle中实现这一目标?

来自postgres手册:

  

SELECT DISTINCT ON(表达式[,...])仅保留第一行   给定表达式求值等于的每组行。该   DISTINCT ON表达式使用与之相同的规则进行解释   ORDER BY(见上文)。请注意,每组的“第一行”是   不可预测,除非使用ORDER BY来确保所需的行   首先出现。

例如,对于给定的表:

 col1 | col2 
------+------
 A    | AB
 A    | AD
 A    | BC
 B    | AN
 B    | BA
 C    | AC
 C    | CC

升序排序:

> select distinct on(col1) col1, col2 from tmp order by col1, col2 asc;
 col1 | col2 
------+------
 A    | AB
 B    | AN
 C    | AC

降序排序:

> select distinct on(col1) col1, col2 from tmp order by col1, col2 desc;
 col1 | col2 
------+------
 A    | BC
 B    | BA
 C    | CC

2 个答案:

答案 0 :(得分:38)

通过使用first_value()函数或使用rank()row_number()函数之一,可以在Oracle中复制相同的效果。

这两种变体也适用于Postgres。

<强> first_value()

select distinct col1, 
first_value(col2) over (partition by col1 order by col2 asc)
from tmp

first_value给出了分区的第一个值,但是每行重复一次,因此有必要将它与distinct结合使用,为每个分区获取一行。

row_number() / rank()

select col1, col2 from (
  select col1, col2, 
  row_number() over (partition by col1 order by col2 asc) as rownumber 
  from tmp
) foo
where rownumber = 1

在此示例中,使用row_number()替换rank()会产生相同的结果。

此变体的一个特性是,只需将rownumber = 1更改为{{{}}即可用于获取给定分区的前N 行(例如“last 3 updated”) 1}}。

答案 1 :(得分:2)

如果您有两个以上的字段,那么请使用beerbajays答案作为子查询(以DESC顺序注释):

select col1,col2, col3,col4 from tmp where col2 in
(
select distinct 
first_value(col2) over (partition by col1 order by col2 DESC) as col2
from  tmp
--WHERE you decide conditions
)