0

那个设定

我有一个包含两个表的数据库。其中一个用于收件箱消息 ( inbox),另一个用于发件箱消息 ( outbox)。它们都有相同的结构和一些记录。

+------------------------------------------------------------+
| inbox                                                      |
+------------------------------------------------------------+
| messageID | from  | to    | messageText | timestamp        |
+------------------------------------------------------------+
| 1         | userA | userB | sometext    | 2013-06-19 10:30 |
| 2         | userB | userC | sometext    | 2013-06-19 10:40 |
| 3         | userC | userA | sometext    | 2013-06-19 10:50 |
+------------------------------------------------------------+

+------------------------------------------------------------+
| outbox                                                     |
+------------------------------------------------------------+
| messageID | from  | to    | messageText | timestamp        |
+------------------------------------------------------------+
| 1         | userA | userC | sometext    | 2013-06-19 10:20 |
| 2         | userC | userB | sometext    | 2013-06-19 10:30 |
| 3         | userB | userA | sometext    | 2013-06-19 10:35 |
+------------------------------------------------------------+

问题

我需要从特定用户的每个对话中选择每条最后一条消息(在这种情况下 - 我想从 userA 的对话中检索每条最后一条消息)在消息所在的任何表中 - 收件箱或发件箱。我已设法使用以下查询从收件箱和发件箱中为每个对话选择最后一条消息:

SELECT * FROM
(
    SELECT from, to, timestamp, messageText, messageID
    FROM inbox
    WHERE to = 'userA'
    ORDER BY timestamp DESC
)
AS tmp_table GROUP BY from
UNION
SELECT * FROM
(
    SELECT from, to, timestamp, messageText, messageID
    FROM outbox 
    WHERE from = 'userA'
    ORDER BY timestamp DESC
)
AS tmp_table GROUP BY to
ORDER BY timestamp DESC

因此,现在我需要检查哪条消息较新 - 收件箱中的消息或发件箱中的消息(当然,如果两个用户之间的两个表中都存在消息)并且只返回最新消息。

或者也许我的方法是彻头彻尾的愚蠢 - 请评论:D 谢谢。

4

2 回答 2

2

只需从每个表中获取前 1 条记录,然后合并结果:

SELECT 'outbox', *
FROM outbox
WHERE `from` = 'userA'
ORDER BY timestamp DESC
LIMIT 1

UNION ALL

SELECT 'inbox', *
FROM inbox
WHERE `from` = 'userA'
ORDER BY timestamp DESC
LIMIT 1

笔记:

1)注意周围的反引号fromFROM是太阳下几乎每个 sql 数据库中的保留字,因此如果不出现语法错误,您的查询将永远无法工作
2) 请注意两个子查询中的硬编码'inbox''outbox'字符串 - 它们在那里告诉您找到的记录在哪个表来自。

于 2013-06-19T19:17:08.950 回答
1

根据您的表上设置的索引,可能可以编写一个执行速度更快的查询,但这应该可以工作:

select 
    sq.main_user, 
    sq.other_user, 
    coalesce(i.messageText, o.messageText) messageText
from 
   (select 
        main_user, other_user, max(msg_time) last_msg 
    from
        (select 
             `from` main_user, `to` other_user, `timestamp` msg_time 
         from outbox
         where `from` = 'userA'
         union all
         select 
             `to` main_user, `from` other_user, `timestamp` msg_time 
         from inbox
         where `to` = 'userA') uq
      group by main_user, other_user) sq
left join 
    outbox o on sq.main_user = o.`from` and sq.last_msg = o.`timestamp`
left join 
    inbox i on sq.main_user = i.`to` and sq.last_msg = i.`timestamp`

where(如果您想查看所有用户的对话,而不仅仅是 userA,请忽略最里面的子查询中的子句。)

于 2013-06-20T08:32:47.733 回答