Oracle相当于Postgres的DISTINCT ON?

bee*_*jay 24 sql oracle postgresql

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

来自postgres手册:

SELECT DISTINCT ON(expression [,...])仅保留给定表达式求值的每组行的第一行.使用与ORDER BY相同的规则解释DISTINCT ON表达式(参见上文).请注意,除非使用ORDER BY确保首先显示所需的行,否则每个集合的"第一行"都是不可预测的.

例如,对于给定的表:

 col1 | col2 
------+------
 A    | AB
 A    | AD
 A    | BC
 B    | AN
 B    | BA
 C    | AC
 C    | CC
Run Code Online (Sandbox Code Playgroud)

升序排序:

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

降序排序:

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

bee*_*jay 39

通过使用该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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

更换row_number()rank()在本例中产生同样的结果.

这种变体的一个特征是它可以用来简单地通过改变来获取给定分区的前N行(例如"最后3次更新").rownumber = 1rownumber <= N

  • +1:`first_value()`变体是'DISTINCT ON`的一个非常聪明的模拟.我应该把它建成[jOOQ](http://www.jooq.org) (2认同)
  • 如果我想要来自2个字段的DISTINCT和来自所有其他字段的相应值,如何应用这个? (2认同)