Как выбрать строку с максимальным значением в столбце для каждой группы в HSQL? - PullRequest
0 голосов
/ 08 мая 2018

У меня есть таблица с именем PERSON в базе данных HSQL, подобная этой:

NAME(PK) | AGE | CITY   | ... many more here ... | 
--------------------------------------------------
aaa      |  12 |   nyc  | ...
bbb      |  12 |   nyc  | ...
ccc      |  10 |   nyc  | ...
ddd      |  34 |    la  | ...
eee      |  10 |    la  | ...

Для каждого города мне нужно выбрать запись с максимальным возрастом. Если для данного города существует несколько записей с максимальным возрастом, мне все равно нужно выбрать ровно одну запись для этого города (но ее можно выбрать произвольно).

Так что в приведенном выше примере мне нужен этот результат:

NAME(PK) | AGE | CITY | ... many more here ... | 
--------------------------------------------------
aaa      |  12 |  nyc | ...
ddd      |  34 |   la | ...

и было бы хорошо, если бы я получил bbb вместо aaa, но не хорошо, чтобы получить aaa и bbb.

Простое использование группировки по столбцу города и параметра max (age) в качестве функции агрегирования не работает, поскольку это не позволяет мне выбирать другие столбцы, кроме возраста и города, поскольку их нет в совокупности. Я попытался создать группу, а затем соединить результаты с таблицей, но таким образом мне не удается избавиться от записей с дублирующимся максимальным возрастом. Этот запрос:

SELECT NAME, CITY, AGE, [... many more here ...] 
FROM ( 
    SELECT max(age) AS maxAge, city 
    FROM PERSON
    GROUP BY CITY
) AS x
JOIN PERSON AS p 
ON p.city = x.city AND p.age = x.maxAge

выход:

NAME(PK) | AGE | CITY | ... many more here ... | 
--------------------------------------------------
aaa      |  12 |  nyc | ...
bbb      |  12 |  nyc | ...
ddd      |  34 |   la | ...

с двумя записями для nyc, где должна быть только одна.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Современная альтернатива SQL для коррелированного решения подзапроса - это ключевое слово LATERAL:

SELECT * FROM 
 (SELECT DISTINCT CITY FROM PERSON) CITIES, 
 LATERAL 
 (SELECT * FROM PERSON WHERE CITY = CITIES.CITY ORDER BY AGE DESC LIMIT 1)
0 голосов
/ 08 мая 2018

Если вас не волнует порядок, вы можете использовать коррелированный subquery:

select * 
from PERSON p
where name = (select name 
              from PERSON 
              where CITY = p.City 
              order by AGE desc, name asc -- neglate name if you want arbitrary ordering 
              LIMIT 1);

Это выберет только одно название для каждого города.

...