sql - ora2pg - ¿Oracle equivalente a DISTINCT ON de Postgres?
oracle to postgresql online (2)
El mismo efecto se puede replicar en Oracle utilizando la función first_value()
o usando una de las funciones rank()
o row_number()
.
Ambas variantes también funcionan en Postgres.
first_value()
select distinct col1,
first_value(col2) over (partition by col1 order by col2 asc)
from tmp
first_value
proporciona el primer valor para la partición, pero lo repite para cada fila, por lo que es necesario usarlo en combinación con distinct
para obtener una sola fila para cada partición.
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
Reemplazar row_number()
con rank()
en este ejemplo produce el mismo resultado.
Una característica de esta variante es que se puede usar para obtener las primeras N filas para una partición determinada (por ejemplo, "las últimas 3 actualizaciones") simplemente cambiando rownumber = 1
a rownumber <= N
En postgres, puede consultar el primer valor de en un grupo con DISTINCT ON
. ¿Cómo se puede lograr esto en Oracle?
Del manual de postgres:
SELECT DISTINCT ON (expresión [, ...]) mantiene solo la primera fila de cada conjunto de filas donde las expresiones dadas son iguales. Las expresiones DISTINCT ON se interpretan usando las mismas reglas que para ORDER BY (ver arriba). Tenga en cuenta que la "primera fila" de cada conjunto es impredecible a menos que se utilice ORDER BY para garantizar que la fila deseada aparezca primero.
Por ejemplo, para una tabla dada:
col1 | col2
------+------
A | AB
A | AD
A | BC
B | AN
B | BA
C | AC
C | CC
Tipo ascendente:
> select distinct on(col1) col1, col2 from tmp order by col1, col2 asc;
col1 | col2
------+------
A | AB
B | AN
C | AC
Tipo descendente:
> select distinct on(col1) col1, col2 from tmp order by col1, col2 desc;
col1 | col2
------+------
A | BC
B | BA
C | CC
Si tiene más de dos campos, utilice la respuesta de beerbajays como una sub consulta (nota en orden 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
)