获取许多用户之间的最新消息

时间:2016-12-08 04:30:56

标签: sql postgresql join many-to-many limit

在我的应用中,用户

CREATE TABLE users (
    id bigserial PRIMARY KEY,
    username varchar(50) NOT NULL
);

可以发送消息

CREATE TABLE messages (
    id bigserial PRIMARY KEY,
    from_id bigint NOT NULL REFERENCES users ON DELETE RESTRICT,
    body text NOT NULL CHECK (body <> ''),
    created_at timestamp(0) NOT NULL DEFAULT LOCALTIMESTAMP(0)
);

对许多收件人

CREATE TABLE message_recipients (
    message_id bigint NOT NULL REFERENCES messages ON DELETE CASCADE,
    user_id bigint NOT NULL REFERENCES users ON DELETE RESTRICT,
    PRIMARY KEY (message_id, user_id)
);

请参阅this SQL Fiddle

我如何SELECT一组用户之间的最新消息(例如20条)?

例如,如何在用户1,2和3之间获取20条最新消息?即,如何将消息限制为1已发送给2&amp; 2的最新消息。 3,2已发送给1&amp; 3和3已经发送给1&amp; 2?

注意:我不想将消息分配给频道。我想通过发件人和他们过滤它们接收机。

相关问题:Get a subset of messages between specific users

1 个答案:

答案 0 :(得分:1)

首先汇总每条消息的参与者,然后您可以匹配参与者列表。

WITH target_group (members) AS (
  VALUES (ARRAY [1, 2, 3] :: BIGINT [])
), message_group AS (
    SELECT
      -- message id
      m.id,
      -- aggregate the ids of all message parties
      array_agg(mr.user_id) || m.from_id AS members
    FROM message_recipients mr
      JOIN messages m ON m.id = mr.message_id
      JOIN target_group tg ON tg.members @> ARRAY [m.from_id]
    GROUP BY m.id
)
SELECT
  m.id,
  m.body
FROM message_group mg
  JOIN messages m ON m.id = mg.id
  JOIN target_group tg ON tg.members @> mg.members AND array_length(tg.members, 1) = array_length(mg.members, 1)
ORDER BY m.id DESC
LIMIT 20;