查询以获取用户收件箱的最后一次会话

时间:2013-03-24 07:52:10

标签: postgresql

我需要一个特定的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 个答案:

答案 0 :(得分:1)

根据我的理解,您需要根据每个用户(最近10次最近的对话)获取对话的最新消息

更新:我修改了查询以获取每个用户对话的latest_conversation_message_id

以下查询获取user_id = 2的详细信息,您可以修改users.id = 2以获取其他任何用户

SQLFiddle ,希望这能解决您的目的

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

信息:查询获取与任何其他用户的每次对话的最新消息,如果user_id 2,则向user_id 3发送消息,该消息也会显示,因为它表示对话的开始。显示与任何其他用户的每次对话的最新消息

答案 1 :(得分: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

答案 2 :(得分:0)

将其粘贴到WHERE子句

之后
ORDER BY "ColumnName" [ASC, DESC]

UNION Description at W3Schools它结合了这两个陈述的结果。

SELECT "ColumnName" FROM "TableName"
UNION
SELECT "ColumnName" FROM "TableName"

答案 3 :(得分: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,或者在最近检索的数量非常大的情况下。尽管如此,还是有点不清楚。如果有疑问,我会选择以前的版本。