2015-12-28 2 views
1

В PostgreSQL У меня есть таблица со следующими значениями:SQL: Найти максимальный кортеж

year | month | val 
-----|-------|------ 
2014 | 1 | x 
2014 | 12 | y 
2015 | 1 | z 

Существует иерархическая связь между годом и месяцем, и я хочу найти Вэла максимального кортежа (год, месяц). Таким образом, в этом примере я хочу вернуть val 'z', так как 2015 - максимальный год, а 1 - максимальный месяц в течение этого года. Это может быть достигнуто с помощью внутреннего запроса:

SELECT val 
FROM (
    SELECT val, row_number() OVER (ORDER BY YEAR DESC, MONTH DESC) AS r 
    FROM test 
) foo 
WHERE r=1 

http://sqlfiddle.com/#!15/17fb6/16 См Но есть более простой и аккуратнее способ сделать это?

+0

У вас есть 'UNIQUE' ограничение на' (год, месяц'), если вы не используете 'RANK()' для получения связей ** [demo] (http://sqlfiddle.com/#!15/82557/1/0) ** – lad2025

ответ

2

Использование ORDER BY с LIMIT 1:

SELECT val 
FROM test 
ORDER BY year DESC, month DESC 
LIMIT 1; 
0

Вы можете уйти с не имеющим сортировать все (что и происходит, если вы используете ORDER), делая себя Полусоединение как:

SELECT year, month, val FROM test t1 WHERE NOT EXISTS (
    SELECT 1 FROM test t2 
    WHERE (t2.year = t1.year AND t2.month > t1.month) OR 
     t2.year > t1.year) 

Обратите внимание, что это дает вам все максимальные кортежи, если есть связи. Вы можете указать OR (t1.year = t2.year AND t1.month = t2.month AND t2.ctid > t1.ctid) в условии exists, если хотите одну строку.

+0

Сортировка может быть выполнена в O (n log n). Но мне кажется, что это предложение имеет сложность O (n^2), так же как одно сканирование таблицы для каждой строки, правильно? – matthiash

Смежные вопросы