2016-07-11 1 views
1

Это, вероятно, стандартная проблема, и я отменил некоторые другие ответы , но до сих пор не смог решить мою текущую проблему.Группа postgres по столбцам и внутри группы выбирает другие столбцы с помощью max aggregate

A    B    C 
+----+-------+ +----+------+ +----+------+-------+ 
| id | start | | id | a_id | | id | b_id | name | 
+----+-------+ +----+------+ +----+------+-------+ 
| 1 |  1 | | 1 | 1 | | 1 | 1 | aname | 
| 2 |  2 | | 2 | 1 | | 2 | 2 | aname | 
+----+-------+ | 3 | 2 | | 3 | 3 | aname | 
       +----+------+ | 4 | 3 | bname | 
          +----+------+-------+ 

В английском языке, что я хотел бы, чтобы выполнить это:

  1. Для каждого c.name выберите свою новую запись на основе времени начала в a.start

SQL Я попытался следующий:

SELECT a.id, a.start, c.id, c.name 
FROM a 
INNER JOIN (
    SELECT id, MAX(start) as start 
    FROM a 
    GROUP BY id 
) a2 ON a.id = a2.id AND a.start = a2.start 
JOIN b 
ON a.id = b.a_id 
JOIN c 
on b.id = c.b_id 
GROUP BY c.name; 

Он терпит неудачу с ошибками, такими как:

ERROR: column "a.id" must appear in the GROUP BY clause or be used in an aggregate function Position: 8 

Для удобства мне действительно нужны идентификаторы из запроса, но они не могут группироваться на них, поскольку они уникальны. Вот пример вывода я хотел бы в первом случае выше:

+------+---------+------+--------+ 
| a.id | a.start | c.id | c.name | 
+------+---------+------+--------+ 
| 2 |  2 | 3 | aname | 
| 2 |  2 | 4 | bname | 
+------+---------+------+--------+ 

Вот это Sqlfiddle

Edit - удален второй случай

+0

'GROUP BY cn ame; 'не требуется. –

+0

Я предлагаю удалить второй запрос из этого вопроса (прежде чем кто-нибудь ответит на него), примите ответ, используя 'distinct on', и задайте другой вопрос для второй части. Stack Overflow не предлагает дополнительного кредита. –

ответ

2

Случай 1

select distinct on (c.name) 
    a.id, a.start, c.id, c.name 
from 
    a 
    inner join 
    b on a.id = b.a_id 
    inner join 
    c on b.id = c.b_id 
order by c.name, a.start desc 
; 
id | start | id | name 
----+-------+----+------- 
    2 |  2 | 3 | aname 
    2 |  2 | 4 | bname 

Case 2

select distinct on (c.name) 
    a.id, a.start, c.id, c.name 
from 
    a 
    inner join 
    b on a.id = b.a_id 
    inner join 
    c on b.id = c.b_id 
where 
    b.a_id in (
     select a_id 
     from b 
     group by a_id 
     having count(*) > 1 
    ) 
order by c.name, a.start desc 
; 
id | start | id | name 
----+-------+----+------- 
    1 |  1 | 1 | aname 
+0

Спасибо за такой быстрый ответ! Если мне нужно расширить выделенные до дополнительных столбцов в c, я предполагаю, что просто добавлю его в отдельный оператор, но также и внутри порядка? Кроме того, я предполагаю, что производительность этого будет довольно плохой, так как общее количество строк соединения увеличивается из-за нескольких сортов? –

+0

@DavidE Вы можете добавлять элементы в предложение 'order by' в дополнение к обязательным' c.name' и untier 'a.start'. Список выбора является бесплатным. Проверьте 'объясните анализ' –