我有一张看起来像块历史的表:
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
的记录始终在TRUE
和FALSE
之间交替。
问题:
我想让桌子看起来像:
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
是否有可能实现此结果表?
感谢。
答案 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应该是>=
的日期或时间戳类型。