PostgreSQL排名查询

时间:2013-08-09 01:07:46

标签: sql postgresql

我在postgreSQL表中有数据如下,

pkid  id  timestamp              isactive
-----------------------------------------
   1  1   "2013-08-08 10:10:10"  0
   2  1   "2013-08-08 10:11:10"  0
   3  1   "2013-08-08 10:12:10"  0
   4  1   "2013-08-08 10:13:10"  1
   5  1   "2013-08-08 10:14:10"  1
   6  1   "2013-08-08 10:15:10"  1
   7  1   "2013-08-08 10:16:10"  1
   8  1   "2013-08-08 10:17:10"  1
   9  1   "2013-08-08 10:18:10"  0
  10  1   "2013-08-08 10:19:00"  0
  11  2   "2013-08-08 09:10:10"  0

我想获得一个查询,以便在它从活动状态变为非活动状态时获得第一条记录,反之亦然,例如每个ID,

   1  1   "2013-08-08 10:10:10"  0
   4  1   "2013-08-08 10:13:10"  1
   9  1   "2013-08-08 10:18:10"  0
  11  2   "2013-08-08 09:10:10"  0

我尝试使用rank()但是它在活动/非活动状态中分配排名值,即rank()(按ID分区,按时间戳排列等效顺序)

 pkid id  timestamp             isactive  rank
 ----------------------------------------------
    1 1  "2013-08-08 10:10:10"   0        1
    2 1  "2013-08-08 10:11:10"   0        2
    3 1  "2013-08-08 10:12:10"   0        3
    4 1  "2013-08-08 10:13:10"   1        1
    5 1  "2013-08-08 10:14:10"   1        2
    6 1  "2013-08-08 10:15:10"   1        3
    7 1  "2013-08-08 10:16:10"   1        4
    8 1  "2013-08-08 10:17:10"   1        5
    9 1  "2013-08-08 10:18:10"   0        4
   10 1  "2013-08-08 10:19:00"   0        5
   11 2  "2013-08-08 09:10:10"   0        1

我希望看到结果为,

pkid  id timestamp              isactive rank
---------------------------------------------
   1  1  "2013-08-08 10:10:10"  0         1
   2  1  "2013-08-08 10:11:10"  0         2
   3  1  "2013-08-08 10:12:10"  0         3
   4  1  "2013-08-08 10:13:10"  1         1
   5  1  "2013-08-08 10:14:10"  1         2
   6  1  "2013-08-08 10:15:10"  1         3
   7  1  "2013-08-08 10:16:10"  1         4
   8  1  "2013-08-08 10:17:10"  1         5
   9  1  "2013-08-08 10:18:10"  0         1
  10  1  "2013-08-08 10:19:00"  0         2
  11  2  "2013-08-08 09:10:10"  0         1

然后我可以选择所有等级== 1并获得状态改变时的时间戳。

1 个答案:

答案 0 :(得分:1)

您可以使用lag()功能执行此操作:

select t.*
from (select t.*,
             lag(isactive) over (partition by id order by timestamp) as prevIsActive
      from t
     ) t
where prevIsActive is NULL or prevIsActive <> IsActive;

如果状态仅在一个方向上进行 - 从非活动状态到活动状态,反之亦然,您只能按照建议的方式进行操作。您的方法将所有活动和非活动组合在一起作为id,从而产生连续编号。