2009-07-16 24 views
0

Скажем, у меня есть таблица «uservalue» со следующими столбцами:Postgresql ВПР

integer user_id 
integer group_id 
integer value 

я могу получить максимальное значение для каждой группы легко:

select max(value) from uservalue group by group_id; 

То, что я хотел бы для он возвращает user_id в каждой группе с самым высоким значением. Функция max в Matlab также вернет индекс максимума, есть ли способ сделать postgresql сделать то же самое?

ответ

1

Правильный способ todo это с подзапросом.

select 
    u.user_id, 
    u.value 
from 
    uservalue u 
join 
    (select groupid, max(value) as max_value from uservalue group by group_id) mv 
    on u.value = mv.max_value and mv.group_id = u.group_id 

Однако я иногда предпочитаю более простой взлом.

select max(value*100000 + user_id) - 100000, max(value) from user_value group by group_id 

Убедившись, что номер (100000) выше, чем у любого пользователя, которого вы ожидаете. Это гарантирует, что только один user_id выбран с теми же значениями, в то время как другой выбирает их оба.

+0

Обратите внимание, что это даст несколько строк назад для каждой группы, если есть несколько пользователей с одинаковым значением. –

+0

Второй запрос возвращает только один, но первый дает им все. Как мой последний отчёт говорит. –

1

Кажется, вы должны быть в состоянии сделать это с помощью запроса взвешивания, что-то вроде:

SELECT DISTINCT 
    group_id, 
    first_value(user_id) OVER w AS user, 
    first_value(value) OVER w AS val 
FROM 
    uservalue 
WINDOW w AS (PARTITION BY group_id ORDER BY value DESC) 

Этого запрос также будет работать, если у вас есть несколько пользователей с одинаковым значением (если не добавить второй столбец ЗАКАЗАТЬ BY вы не будете знать, какой из них вы получите обратно, хотя - но вы получите только один ряд назад на группу)

+0

оконные функции только что вышли в постгрессию и великолепны. Но, если вы не используете последнюю версию, вы немного застряли. –

+0

Правда. Это означает, что есть еще одна веская причина для обновления :-) –