【问题标题】:Oracle equivalent of Postgres' DISTINCT ON?Oracle 相当于 Postgres 的 DISTINCT ON?
【发布时间】:2012-05-09 11:44:57
【问题描述】:

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

来自 postgres 手册:

SELECT DISTINCT ON (表达式 [, ...] ) 只保留第一行 给定表达式计算结果为等于的每组行。这 DISTINCT ON 表达式使用与 for 相同的规则进行解释 订购(见上文)。请注意,每组的“第一行”是 不可预测,除非使用 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

【问题讨论】:

    标签: sql oracle postgresql


    【解决方案1】:

    可以通过使用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 更改为rownumber <= N,它就可以用于获取给定分区的前 N 行(例如“最后 3 个更新”)。

    【讨论】:

    • +1:first_value() 变体非常巧妙地模拟了DISTINCT ON。我应该把它构建到jOOQ
    • 如果我想要 2 个字段的 DISTINCT 和所有其他字段的相应值,如何应用这个?
    • @tumchaaditya - 使用 ROW_NUMBER() 函数!
    【解决方案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
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 2018-08-10
      • 1970-01-01
      • 2011-07-11
      • 1970-01-01
      • 2017-02-24
      • 1970-01-01
      相关资源
      最近更新 更多