假设我们有此消息日志表,该表存储了两个人之间的对话
message own_account reply_batch unix_timestamp conversation_id
Hi f f 1543452938 5b43d
Hello t t 1543453562 5b43d
How are you? f f 1543453814 5b43d
good and you? t t 1543454118 5b43d
I'm good too. f f 1543454344 5b43d
Are you home? f f 1543454950 5b43d
在最后一个own_account
设置为true之后,SQL返回什么行呢?我想在最后一条own_account
消息之后得到最后一条消息。在这种情况下,我们应该返回两行。
I'm good too. f f 1543454344 5b43d
Are you home? f f 1543454950 5b43d
每个对话都通过conversation_id
如果转换中唯一的消息是来自他们的,我希望这些消息返回
答案 0 :(得分:2)
这里是一种选择。第一个计数cnt1
是真实的自己的帐户记录数的累积计数。第二个计数是真实的自己帐户记录的表级总数。我们要针对的记录是这两个计数相等的记录。
SELECT message, own_account, reply_batch, unix_timestamp, conversation_id
FROM
(
SELECT *,
COUNT(CASE WHEN own_account = 't' THEN 1 END) OVER (ORDER BY unix_timestamp) AS cnt1,
COUNT(CASE WHEN own_account = 't' THEN 1 END) OVER () AS cnt2
FROM yourTable
WHERE conversation_id = '5b43d'
) t
WHERE cnt1 = cnt2 AND own_account = 'f';
答案 1 :(得分:1)
这将扫描表两次,但是如果我们在(cinversation_id, unix_timestamp)
上有索引,则会很快:
WITH lastmsg AS (
SELECT max(unix_timestamp) AS ts
FROM messages
WHERE own_account
AND conversation_id = '5b43d')
SELECT * FROM messages
CROSS JOIN lastmsg
WHERE unix_timestamp > COALESCE(ts, '-infinity'::timestamptz)
AND conversation_id = '5b43d';
答案 2 :(得分:0)
我喜欢蒂姆的回答。 。 。有点。我认为这个版本更清晰:
SELECT message, own_account, reply_batch, unix_timestamp, conversation_id
FROM (SELECT t.*,
MAX(unix_timestamp) FILTER (WHERE own_account = 't') OVER
(PARTITION BY conversation_id
ORDER BY unix_timestamp
) AS my_max_unix_timestamp
FROM t
WHERE conversation_id = '5b43d'
) t
WHERE unix_timestamp > my_max_unix_timestamp;
这几乎是您问题的直接翻译。子查询为每个对话(或给定对话)计算“我的消息”的最后时间戳。然后,外部where
选择晚于该消息的消息。