Postgres:查询一个用户的最近2条记录,它们的created_at时间相差小于1秒?

时间:2018-06-30 01:02:35

标签: sql postgresql

我有一张桌子

foreach (string line in textBox16.Lines)
{
    if (File.ReadAllLines("watcher.txt").Contains(textBox16.Text))
    {
        //do nothing
    }
    else
    {
        MessageBox.Show("Item not on list");
    }
}

一个create table Account( userId: INT NOT NULL, status: TEXT NOT NULL, created_at: TIMESTAMP NOT NULL ) 可以有多个帐户,状态可以为userIdACTIVE。我希望最近的帐户是CANCELLED,而一个用户只能有1个ACTIVE。当前有ACTIVE account个帐户具有userIds,但该用户的最新帐户是ACTIVE,这些是我要识别的帐户。

是否存在查询以查找两个最近的帐户(通过CANCELLED,其中一个处于活动状态,另一个处于“已取消”状态(或其他任何文本)。

2 个答案:

答案 0 :(得分:0)

您可以使用row_number()获得最后两个帐户。

SELECT *
       FROM (SELECT *,
                    row_number() OVER (PARTITION BY a1.userid
                                       ORDER BY a1.created_at DESC) rn
                    FROM account a1) a2
       WHERE a2.rn <= 2;

但这也会返回单个帐户(每个用户)。如果您不希望加入一个子查询来获取每个用户的帐户数量,并检查该计数是否> = 2。

SELECT *
       FROM (SELECT *,
                    row_number() OVER (PARTITION BY a1.userid
                                       ORDER BY a1.created_at DESC) rn
                    FROM account a1) a2
            INNER JOIN (SELECT a3.userid,
                               count(*) c
                               FROM account a3
                               GROUP BY a3.userid) a4
                       ON a4.userid = a2.userid                
       WHERE a2.rn <= 2
             AND a4.c >= 2;

但是您也可以直接识别有问题的帐户。使用带有GROUP BY userid的子查询为每个用户获取max(created_at)INNER JOIN生成帐户并过滤WHERE status = 'CANCELLED'。使用EXISTS检查该用户是否曾经拥有'ACTIVE'帐户。再次加入以获得该用户的所有帐户。

SELECT *
       FROM account a1
            INNER JOIN (SELECT a2.userid
                               FROM account a2
                                    INNER JOIN (SELECT a3.user_id,
                                                       max(a3.created_at) created_at
                                                       FROM account a3
                                                       GROUP BY a3.userid) a4
                                               ON a4.userid = a2.user_id
                                                  AND a4.created_at = a3.created_at
                               WHERE a1.status = 'CANCELLED'
                                     AND EXISTS (SELECT *
                                                        FROM account a5
                                                        WHERE a5.userid = a1.userid
                                                              AND a5.status = 'ACTIVE')) a6
                       ON a6.userid = a1.userid;

答案 1 :(得分:0)

我将使用lag()distinct on来获取最新状态:

select distinct on (user_id) a.*
from (select a.*,
             lag(status) over (partition by user_id order by created_at) as prev_status
      from account a
     ) a
order by user_id, created_at desc;

如果您想要被取消但在紧接之前处于活动状态的那些,请使用子查询:

select a.*
from (select distinct on (user_id) a.*
      from (select a.*,
                   lag(status) over (partition by user_id order by created_at) as prev_status
            from account a
           ) a
      order by user_id, created_at desc
     ) a
where status = 'CANCELLED' and prev_status = 'ACTIVE'