Вопрос по postgresql, sql – Oracle эквивалент Postgres 'DISTINCT ON?

24

В postgres вы можете запросить первое значение в группе сDISTINCT ON. How can this be achieved in Oracle?

Из руководства postgres:

SELECT DISTINCT ON ( expression [, ...] ) keeps only the first row of each set of rows where the given expressions evaluate to equal. The DISTINCT ON expressions are interpreted using the same rules as for ORDER BY (see above). Note that the "first row" of each set is unpredictable unless ORDER BY is used to ensure that the desired row appears first.

Например, для данной таблицы:

 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   ответа
38

first_value() функция или с помощью одного изrank() или жеrow_number() функции.

Оба варианта также работают в 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() в этом примере дает тот же результат.

Особенностью этого варианта является то, что он может быть использован для полученияfirst N строки для данного раздела (например, «последние 3 обновлены») просто путем измененияrownumber = 1 вrownumber <= N.

+1:first_value() вариант довольно умная симуляцияDISTINCT ON, Я должен встроить это вjOOQ
Как применить это, если я хочу DISTINCT от 2 полей и соответствующих значений от всех других полей?
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
)

Похожие вопросы