postgresql: как получить первичный ключ из группы по предложению? - PullRequest
7 голосов
/ 29 октября 2011

Это запрос, который выбирает набор желаемых строк:

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 ]

5 голосов
/ 29 октября 2011

Если вам все равно, какой id вы получите, вам просто нужно обернуть ваш id в какую-либо агрегатную функцию, которая гарантированно даст вам действительный id.Вспоминаются агрегаты 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
3 голосов
/ 29 октября 2011

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

PostgreSQL довольно строг - он даже не догадывается о чем вы.

  1. вы можете запустить подзапрос
  2. Вы можете выполнить другой запрос на основе b,c,d,e
  3. Вы можете использовать функцию группировки array_agg для получения массива id значений на запись.

См. Этот вопрос: Postgresql GROUP_CONCAT эквивалент?

Я предлагаю вам рассмотреть # 3 как наиболее эффективную из возможностей.

Надеюсь, это поможет. Спасибо!

1 голос
/ 29 октября 2011

Это не то, что вы просили, но я подозреваю, что вы пытаетесь сделать, чтобы получить единственную строку, соответствующую максимальному значению одного столбца для каждой группы, определенной несколькими другими столбцами.Например, чтобы найти день, который был самым жарким понедельником / вторником / и т. Д. За весь год.

Лучший способ сделать это - использовать представление, чтобы найти все максимальные значения для групп.Если ваша исходная таблица

create table T as (
  id integer primary key,
  a integer,
  b integer,
  c integer,
  d integer)

, создайте представление "max" как

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) 
1 голос
/ 29 октября 2011

Используйте свой исходный запрос как подзапрос и используйте эти результаты, чтобы присоединиться к исходной таблице, чтобы найти идентификатор.

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
0 голосов
/ 29 октября 2011

просто любопытно, работает ли добавление его в группу по предложению?

select T.id, max(a), b, c, d, e
from T 
group by T.id b, c, d, e;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...