2012-05-09 3 views
22

В postgres вы можете запросить первое значение в группе с DISTINCT ON. Как это можно достичь в Oracle?Oracle эквивалент Postgres 'DISTINCT ON?

В руководстве 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 

ответ

33

Тот же эффект может быть воспроизведен в Oracle либо используя функцию first_value() или используя один f 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() в данном примере дает тот же результат.

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

+2

+1: The 'FIRST_VALUE()' вариант вполне умное моделирование 'DISTINCT ON'. Я должен построить это в [jOOQ] (http://www.jooq.org) –

+2

Как применить это, если я хочу DISTINCT из 2 полей и соответствующих значений из всех других полей? – tumchaaditya

1

Если у вас есть больше, чем два поля, то используйте 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 
) 
Смежные вопросы