列出聊天的最后消息
List last messages of chats
CREATE TABLE message
(`id` int, `from_user_id` text, `to_user_id` text, `created` datetime, `message` text)
;
INSERT INTO message
(`id`, `from_user_id`, `to_user_id`, `created`, `message`)
VALUES
(1, 'a', 'b', '2013-01-14 00:00:00', 'hello'),
(2, 'b', 'a', '2013-01-14 00:00:00', 'world'),
(3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!')
;
我想获取适用于(发送/接收)用户的最后消息。在上面的例子中,只有2个用户(a,b),适用于他们的最后一条消息是id = 3。所以预期结果是
'a', 3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!'
'b', 3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!'
SO中也有类似的问题,我找到的最接近的是
似乎是我想要的,但绕着我的脑袋复杂,也无法使其工作。
我在浏览器中使用 lovefield 和 运行。它支持 sql 语法的连接和子集,但可能无法高级使用。下面的代码给出了所提供用户 ID 的最后一条消息,但我想要所有用户的行。
SELECT m.*
FROM message m
WHERE 'a' in (from_user_id, to_user_id) AND
m.created = (SELECT MAX(m2.created)
FROM message m2
WHERE (m2.from_user_id = m.from_user_id AND m2.to_user_id = m.to_user_id) OR
(m2.from_user_id = m.to_user_id AND m2.to_user_id = m.from_user_id)
)
ORDER BY m.created DESC
Below code gives last message for a provided user id, but I want rows for all users.
您的查询看起来不错。只需删除对特定用户进行过滤的条件,您应该会得到预期的结果:
SELECT m.*
FROM message m
WHERE m.created = (SELECT MAX(m2.created)
FROM message m2
WHERE (m2.from_user_id = m.from_user_id AND m2.to_user_id = m.to_user_id) OR
(m2.from_user_id = m.to_user_id AND m2.to_user_id = m.from_user_id)
)
ORDER BY m.created DESC
Here 是您的 fiddle 的更新版本。我为其他用户添加了更多记录,查询 returns:
id from_user_id to_user_id created message
4 d c 2013-01-17T00:00:00Z yo!!
3 b a 2013-01-15T00:00:00Z hi!!
使用 CTE 和 UNION ALL:
with cte as (
select *,
min(from_user_id, to_user_id) user1,
max(from_user_id, to_user_id) user2,
row_number() over (partition by min(from_user_id, to_user_id) order by created desc) rn1,
row_number() over (partition by max(from_user_id, to_user_id) order by created desc) rn2
from message
)
select user1 as user, id, from_user_id, to_user_id, created, message
from cte
where rn1 = 1
union all
select user2 as user, id, from_user_id, to_user_id, created, message
from cte
where rn2 = 1
order by user
参见demo。
结果:
| user | id | from_user_id | to_user_id | created | message |
| ---- | --- | ------------ | ---------- | ------------------- | ------- |
| a | 3 | b | a | 2013-01-15 00:00:00 | hi!! |
| b | 3 | b | a | 2013-01-15 00:00:00 | hi!! |
使用联合:
with lastmessages as
(select id, from_user_id as user_id, from_user_id, to_user_id, max(created) mx, message
from message group by(from_user_id)
UNION ALL
select id, to_user_id as user_id, from_user_id, to_user_id, max(created) mx, message
from message group by(to_user_id) )
select user_id, id, from_user_id, to_user_id, max(mx) mx, message
from lastmessages
group by user_id;
输出
user_id|id|from_user_id|to_user_id|mx|message
a|3|b|a|2013-01-15 00:00:00|hi!!
b|3|b|a|2013-01-15 00:00:00|hi!!
CREATE TABLE message
(`id` int, `from_user_id` text, `to_user_id` text, `created` datetime, `message` text)
;
INSERT INTO message
(`id`, `from_user_id`, `to_user_id`, `created`, `message`)
VALUES
(1, 'a', 'b', '2013-01-14 00:00:00', 'hello'),
(2, 'b', 'a', '2013-01-14 00:00:00', 'world'),
(3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!')
;
我想获取适用于(发送/接收)用户的最后消息。在上面的例子中,只有2个用户(a,b),适用于他们的最后一条消息是id = 3。所以预期结果是
'a', 3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!'
'b', 3, 'b', 'a', '2013-01-15 00:00:00', 'hi!!'
SO中也有类似的问题,我找到的最接近的是
我在浏览器中使用 lovefield 和 运行。它支持 sql 语法的连接和子集,但可能无法高级使用。下面的代码给出了所提供用户 ID 的最后一条消息,但我想要所有用户的行。
SELECT m.*
FROM message m
WHERE 'a' in (from_user_id, to_user_id) AND
m.created = (SELECT MAX(m2.created)
FROM message m2
WHERE (m2.from_user_id = m.from_user_id AND m2.to_user_id = m.to_user_id) OR
(m2.from_user_id = m.to_user_id AND m2.to_user_id = m.from_user_id)
)
ORDER BY m.created DESC
Below code gives last message for a provided user id, but I want rows for all users.
您的查询看起来不错。只需删除对特定用户进行过滤的条件,您应该会得到预期的结果:
SELECT m.*
FROM message m
WHERE m.created = (SELECT MAX(m2.created)
FROM message m2
WHERE (m2.from_user_id = m.from_user_id AND m2.to_user_id = m.to_user_id) OR
(m2.from_user_id = m.to_user_id AND m2.to_user_id = m.from_user_id)
)
ORDER BY m.created DESC
Here 是您的 fiddle 的更新版本。我为其他用户添加了更多记录,查询 returns:
id from_user_id to_user_id created message
4 d c 2013-01-17T00:00:00Z yo!!
3 b a 2013-01-15T00:00:00Z hi!!
使用 CTE 和 UNION ALL:
with cte as (
select *,
min(from_user_id, to_user_id) user1,
max(from_user_id, to_user_id) user2,
row_number() over (partition by min(from_user_id, to_user_id) order by created desc) rn1,
row_number() over (partition by max(from_user_id, to_user_id) order by created desc) rn2
from message
)
select user1 as user, id, from_user_id, to_user_id, created, message
from cte
where rn1 = 1
union all
select user2 as user, id, from_user_id, to_user_id, created, message
from cte
where rn2 = 1
order by user
参见demo。
结果:
| user | id | from_user_id | to_user_id | created | message |
| ---- | --- | ------------ | ---------- | ------------------- | ------- |
| a | 3 | b | a | 2013-01-15 00:00:00 | hi!! |
| b | 3 | b | a | 2013-01-15 00:00:00 | hi!! |
使用联合:
with lastmessages as
(select id, from_user_id as user_id, from_user_id, to_user_id, max(created) mx, message
from message group by(from_user_id)
UNION ALL
select id, to_user_id as user_id, from_user_id, to_user_id, max(created) mx, message
from message group by(to_user_id) )
select user_id, id, from_user_id, to_user_id, max(mx) mx, message
from lastmessages
group by user_id;
输出
user_id|id|from_user_id|to_user_id|mx|message
a|3|b|a|2013-01-15 00:00:00|hi!!
b|3|b|a|2013-01-15 00:00:00|hi!!