SQL在条件后获取最后一行

时间:2018-11-29 06:48:40

标签: sql postgresql

假设我们有此消息日志表,该表存储了两个人之间的对话

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

进行跟踪

如果转换中唯一的消息是来自他们的,我希望这些消息返回

3 个答案:

答案 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选择晚于该消息的消息。