Postgresql加入同一个表

时间:2018-01-24 13:42:33

标签: sql postgresql

我有一张看起来像块历史的表:

id  user_id admin_id    when_blocked    block   reason
1   1       4           05.05.17        TRUE    flood
2   1       4           06.05.17        FALSE   
3   1       4           07.05.17        TRUE    flood
4   1       4           08.05.17        FALSE   
5   1       5           09.05.17        TRUE    cheating

其中block列表示阻止操作(TRUE为阻止,FALSE为阻止)。只有先前block未被阻止,才会显示新的user记录。因此,具有相同user_id的记录始终在TRUEFALSE之间交替。

问题:

我想让桌子看起来像:

user_id admin_id    when_blocked    reason   when_unblocked
1       4           05.05.17        flood    06.05.17       
1       4           07.05.17        flood    08.05.17     
1       5           09.05.17        cheating null

是否有可能实现此结果表?

感谢。

3 个答案:

答案 0 :(得分:4)

我认为你只想要lead(),但也需要一个子查询:

select user_id, admin_id, when_blocked, reason, next_when_blocked as when_unblocked
from (select bh.*,
             lead(when_blocked) over (partition by user_id, admin_id order by id) as next_when_blocked
      from block_history bh
     ) bh
where block;

这假设值是交错的 - 如您的示例和解释所暗示的那样。

答案 1 :(得分:1)

https://www.db-fiddle.com/f/6N1EaoeAmegfdvgg9ELDHn/0

select distinct on (coalesce(unblocked_id, id))
    user_id, admin_id, when_blocked, reason, when_unblocked
from
    (select * from history where block) b
    left join
    (
        select id as unblocked_id, when_blocked as when_unblocked
        from history
        where not block
    ) nb on b.id < nb.unblocked_id
order by coalesce(unblocked_id, id), id
;
 user_id | admin_id | when_blocked |  reason  | when_unblocked 
---------+----------+--------------+----------+----------------
       1 |        4 | 2017-05-05   | flood    | 2017-05-06
       1 |        4 | 2017-05-05   | flood    | 2017-05-08
       1 |        5 | 2017-05-09   | cheating | 

答案 2 :(得分:0)

我喜欢Gordon Linoffs用lead回答,如果表格中有很多行,它可能会更快,但我认为这个选择更容易包围:

select user_id, admin_id, when_blocked, reason,
  ( select min(when_blocked)
    from history
    where not block
    and user_id = h.user_id
    and when_blocked >= h.when_blocked ) when_unblocked
from history h
where block
order by when_blocked, user_id;

列when_blocked应该是>=的日期或时间戳类型。