PostgreSQL присоединяется к самой последней записи между таблицами - PullRequest
2 голосов
/ 26 ноября 2011

У меня есть две таблицы, относящиеся к этому вопросу: conversations имеет много messages. Основная структура (только с соответствующими столбцами) выглядит следующим образом:

conversations (
  int id (PK)
)

create table conversation_participants (
  int id (PK),
  int conversation_id (FK conversations),
  int user_id (FK users),
  unique key on [conversation_id, profile_id]
)

create table messages (
  int id (PK),
  int conversation_id (FK conversations),
  int sender_id (FK users),
  int recipient_id (FK users),
  text body
)

Для каждой записи разговора, с учетом user_id Я хочу получить:

  • все разговоры, в которых участвовал пользователь (т. Е. conversations.*)
  • присоединился к самому последнему соответствующему сообщению (т. Е. order by messages.id desc limit 1)
  • разговоров, упорядоченных по их последнему идентификатору сообщения (т.е. упорядочены по messages.id desc)

К сожалению, вся справочная информация по запросам, которую я могу найти для чего-либо подобного, относится к MySQL, а в PostgreSQL это не работает. Самое близкое, что я нашел, это этот ответ по StackOverflow , который дает пример синтаксиса select distinct on (...). Однако, если я просто делаю это неправильно, я не могу выстроить результаты в правильном порядке, учитывая ограничения группировки, которые мне нужны с этим методом.

Ответы [ 2 ]

6 голосов
/ 26 ноября 2011

Вся информация находится в таблице «сообщения», другие таблицы вам не нужны:

SELECT 
    id, 
    body,
    c.* -- content from conversations 
FROM messages 
    JOIN
        (SELECT MAX(id) AS id, conversation_id 
        FROM messages 
        WHERE 1 IN(sender_id, recipient_id) -- the number is the userid, should be dynamic
        GROUP BY conversation_id) sub
        USING(id, conversation_id)
    JOIN conversations c ON c.id = messages.conversation_id
ORDER BY
    id DESC;

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

1 голос
/ 26 ноября 2011

Попробуйте это:

select
    *
from
    conversation_participants cp

    join conversations c on
    c.id = cp.conversation_id

    -- assuming you only want the conversations where a
    -- message has been left. otherwise use left join
    join messages m on
    m.conversation_id = cp.conversation_id
    and m.id = (
            select
                    id
            from
                    messages _m
            where
                    _m.conversation_id = m.conversation_id
                    and sender_id = 1
            order by
                    id desc
            limit 1
    )
where
        cp.user_id = 1
order by
        m.id desc;
...