2

我需要一个特定的 SQL 查询来为用户收件箱选择最后 10 个对话。收件箱仅显示与每个用户的对话(线程) - 它从对话中选择最后一条消息并将其显示在收件箱中。

已编辑。

预期结果:latest message从每个10 latest conversations. Facebook 以相同方式显示最新对话

还有一个问题。如何在pagination下一页中显示来自以前最新对话的下 10 条最新消息?

数据库中的私人消息如下所示:

| id | user_id | recipient_id | text
| 1  | 2       | 3            | Hi John!
| 2  | 3       | 2            | Hi Tom! 
| 3  | 2       | 3            | How are you? 
| 4  | 3       | 2            | Thanks, good! You?
4

4 回答 4

2

As per my understanding, you need to get the latest message of the conversation on per-user basis (of the last 10 latest conversations)

Update: I have modified the query to get the latest_conversation_message_id for every user conversation

The below query gets the details for user_id = 2, you can modify, users.id = 2 to get it for any other user

SQLFiddle, hope this solves your purpose

SELECT
    user_id, 
    users.name, 
    users2.name as sent_from_or_sent_to,
    subquery.text as latest_message_of_conversation
FROM
    users
    JOIN
    (
    SELECT
        text,
        row_number() OVER ( PARTITION BY user_id + recipient_id ORDER BY id DESC) AS row_num,
        user_id,
        recipient_id,
        id
    FROM
        private_messages
    GROUP BY
        id,
        recipient_id,
        user_id,
        text
    ) AS subquery ON ( ( subquery.user_id = users.id OR subquery.recipient_id = users.id)  AND row_num = 1 )
    JOIN users as users2 ON ( users2.id = CASE WHEN users.id = subquery.user_id THEN subquery.recipient_id ELSE subquery.user_id END )
WHERE
    users.id = 2
ORDER BY
    subquery.id DESC
LIMIT 10

Info: The query gets the latest message of every conversation with any other user, If user_id 2, sends a message to user_id 3, that too is displayed, as it indicates the start of a conversation. The latest message of every conversation with any other user is displayed

于 2013-03-24T08:40:34.440 回答
1

要解决 pg 中的 groupwise-max,您可以使用DISTINCT ON. 像这样:

SELECT
DISTINCT ON(pm.user_id)
    pm.user_id, 
    pm.text
FROM
    private_messages AS pm
WHERE pm.recipient_id= <my user id>
ORDER BY pm.user_id, pm.id DESC;

http://sqlfiddle.com/#!12/4021d/19

但是,要获得最新的 X,我们必须在子选择中使用它:

SELECT
q.user_id,
q.id,
q.text
FROM
(
SELECT
DISTINCT ON(pm.user_id)
    pm.user_id,
pm.id,
    pm.text
FROM
    private_messages AS pm
WHERE pm.recipient_id=2
ORDER BY pm.user_id, pm.id DESC
  ) AS q
ORDER BY q.id DESC
LIMIT 10;   

http://sqlfiddle.com/#!12/4021d/28

要同时获取已发送和已接收的线程:

SELECT
q.user_id,
q.recipient_id,
q.id,
    q.text
FROM
(
SELECT
DISTINCT ON(pm.user_id,pm.recipient_id)
    pm.user_id,
    pm.recipient_id,
pm.id,
    pm.text
FROM
    private_messages AS pm
WHERE pm.recipient_id=2 OR pm.user_id=2
ORDER BY pm.user_id,pm.recipient_id, pm.id DESC
  ) AS q
ORDER BY q.id DESC
LIMIT 10;

http://sqlfiddle.com/#!12/4021d/42

于 2013-03-24T10:21:39.070 回答
0

将其粘贴在 WHERE 子句之后

ORDER BY "ColumnName" [ASC, DESC]

W3Schools 的 UNION 描述它结合了这 2 个语句的结果。

SELECT "ColumnName" FROM "TableName"
UNION
SELECT "ColumnName" FROM "TableName"
于 2013-03-24T07:55:42.297 回答
0

对于大型数据集,我认为您可能希望尝试运行这两个语句,然后合并结果,因为对 (user_id 和 id) 或 (recipient_id 和 id) 的索引扫描应该非常有效地获取 10 个最近的对话每种类型。

with sent_messages as (
  SELECT   *
  FROM     private_messages
  WHERE    user_id = my_user_id
  ORDER BY id desc
  LIMIT    10),
received_messages as (  SELECT   *
  FROM     private_messages
  WHERE    recipient_id = my_user_id
  ORDER BY id desc
  LIMIT    10),
all_messages as (
  select *
  from   sent_messages
  union all
  select *
  from   received_messages)
select   *
from     all_messages
order by id desc
limit    10

编辑:实际上另一个值得尝试的查询可能是:

select *
from   private_messages
where  id in (
         select id
         from   (
           SELECT   id
           FROM     private_messages
           WHERE    user_id = my_user_id
           ORDER BY id desc
           LIMIT    10
           union all
           SELECT   id
           FROM     private_messages
           WHERE    recipient_id = my_user_id
           ORDER BY id desc
           LIMIT    10) all_ids
          order by id desc
          limit 10) last_ten_ids
order by id desc

这在 9.2+ 中可能会更好,其中单独的索引可用于获取 id,或者在要检索的最新数字非常大的情况下。尽管如此,仍然有点不清楚。如果有疑问,我会选择以前的版本。

于 2013-03-24T10:28:55.023 回答