列出聊天的最新消息

时间:2019-11-15 20:49:31

标签: sql sqlite lovefield

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中也有类似的问题,我发现最接近的是here

last answer似乎是我想要的,但是缠住我的头很复杂,而且也无法正常工作。

我使用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

sqlfiddle

3 个答案:

答案 0 :(得分:1)

  

下面的代码给出了提供的用户ID的最后一条消息,但我希望所有用户都显示行。

您的查询看起来不错。只需删除针对特定用户进行过滤的条件,即可获得预期的结果:

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 是您的提琴的更新版本。我为其他用户添加了一些记录,查询返回:

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!!

答案 1 :(得分:1)

使用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!!    |

答案 2 :(得分:0)

使用UNION:

package require Tk

lappend info [format "%-20s = %-1s" "Nombre de seq(s)" 10]
lappend info [format "%-20s = %-1s" "Nombre de page(s)" 1]
lappend info [format "%-20s = %-1s" "Fichier word" {c:/temp/word.docx}]
lappend info [format "%-20s = %-1s" "Fichier simulation" {c:/temp/word.tmp}]

grid [ttk::label .l -text [join $info "\n"]] -row 0 -column 0 -padx 2 -pady 2 -sticky nw 

输出

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;