我需要一个特定的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?
答案 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;
答案 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,或者在最近检索的数量非常大的情况下。尽管如此,还是有点不清楚。如果有疑问,我会选择以前的版本。