postgresql: как получить первичный ключ из предложения group by?
Это запрос, который выбирает набор нужных строк:
select max(a), b, c, d, e
from T
group by b, c, d, e;
таблица имеет первичный ключ, в графе id
.
Я хотел бы идентифицировать эти строки в следующем запросе, получив первичный ключ из каждой из этих строк. Как мне это сделать? Это не работает:
select id, max(a), b, c, d, e
from T
group by b, c, d, e;
ERROR: column "T.id" must appear in the GROUP BY clause or be used in an aggregate function
Я пробовал это, копаясь в некоторых других вопросах postgresql, но не повезло:
select distinct on (id) id, max(a), b, c, d, e
from T
group by b, c, d, e;
ERROR: column "T.id" must appear in the GROUP BY clause or be used in an aggregate function
что мне делать? Я знаю, что может быть только одна id
для каждого результата, потому что это первичный ключ... Я буквально хочу первичный ключ вместе с остальными данными для каждой строки, которую возвращает начальный (рабочий) запрос.
5 ответов
Если вам все равно, какой id
вы получаете, то вам просто нужно обернуть ваш id
в некоторой агрегатной функции, которая гарантированно даст вам действительный id
. The max
и min
Сростки приходят на ум:
-- Or min(id) if you want better spiritual balance.
select max(id), max(a), b, c, d, e
from T
group by b, c, d, e;
в зависимости от ваших данных я думаю, что использование функции окна было бы лучшим планом (благодаря злому Отто для загрузки в голову):
select id, a, b, c, d, e
from (
select id, a, b, c, d, e, rank() over (partition by b,c,d,e order by a desc) as r
from T
) as dt
where r = 1
в силу того, что вы группировка, может (и, скорее всего) быть более одной совпадающей записи (например, более одной id
value) на возвращаемую запись.
PostgreSQL довольно строгий - он не догадается, что вы имеете в виду.
- вы можете запустить подзапрос
- вы можете запустить другой запрос на основе
b,c,d,e
- можно использовать
array_agg
функция группировки, чтобы получить массивid
значения в запись.
см. Этот вопрос: эквивалент Postgresql GROUP_CONCAT?
Я предлагаю вам рассмотреть #3 как наиболее эффективную из возможностей.
надеюсь, что это помогает. Спасибо!
используйте исходный запрос в качестве подзапроса и используйте эти результаты для присоединения к исходной таблице для поиска идентификатора.
SELECT T.id, T.a, T.b, T.c, T.d, T.e
FROM (SELECT max(a) AS MaxA, b, c, d, e
FROM T
GROUP BY b,c,d,e) q
INNER JOIN T
ON T.a = q.MaxA
AND T.b = q.b
AND T.c = q.c
AND T.d = q.d
AND T.e = q.e
- Это не то, что вы просили, но я подозреваю, что вы пытаетесь сделать, чтобы получить одну строку, соответствующую максимальному значению одного столбца для каждой группы определяются несколько других столбцов. Например, найти день, который был самым жарким понедельником / вторником / etc в течение всего года.
лучший способ, который я нашел для этого, использует представление, чтобы найти все максимальные значения для групп. Если ваша исходная таблица
create table T as (
id integer primary key,
a integer,
b integer,
c integer,
d integer)
затем создайте представление "max" as
create view T_maxgroups as
select max(a) as a, b, c, d
from T
group by b, c, d
(Это ваш первоначальный запрос), а затем присоедините это представление к своей таблице, чтобы получить строки с максимальными значениями:
select T.* from T join maxgroups using (a,b,c,d)
juuust curious работает ли добавление его в предложение group by?
select T.id, max(a), b, c, d, e
from T
group by T.id b, c, d, e;