选择直到Postgres中的行匹配

时间:2017-06-13 11:14:40

标签: postgresql

鉴于以下数据结构:

 id | subscription_id | state |         created_at         | ok 
---------+-----------------+-------+----------------------------+----
  1 |               1 | error | 2015-06-30 15:20:03.041045 | f
  2 |               1 | error | 2015-06-30 15:20:04.582907 | f
  3 |               1 | sent  | 2015-06-30 22:50:04.50478  | f
  4 |               1 | error | 2015-06-30 22:50:06.067279 | f
  5 |               1 | error | 2015-07-01 22:50:02.356113 | f

我希望使用state='error'检索上一条消息,直到state包含其他内容。

它应该返回:

 id | subscription_id | state |         created_at         | ok 
---------+-----------------+-------+----------------------------+----
  4 |               1 | error | 2015-06-30 22:50:06.067279 | f
  5 |               1 | error | 2015-07-01 22:50:02.356113 | f

关注this questionlater this one后,我最终得到了以下查询:

SELECT * from (select id, subscription_id, state, created_at,
   bool_and(state='error') 
   OVER (PARTITION BY state order by created_at, id) AS ok 
   FROM messages ORDER by created_at) m2 
   WHERE subscription_id = 1;

但是,鉴于我添加了PARTITION BY state,查询只是忽略了不包含state的所有error,而是显示了这一点:

 id | subscription_id | state |         created_at         | ok 
---------+-----------------+-------+----------------------------+----
  1 |               1 | error | 2015-06-30 15:20:03.041045 | f
  2 |               1 | error | 2015-06-30 15:20:04.582907 | f
  4 |               1 | error | 2015-06-30 22:50:06.067279 | f
  5 |               1 | error | 2015-07-01 22:50:02.356113 | f

如何在查找不同的状态后进行查询,并按照顶部描述的仅仅ids 4和5进行匹配?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,你需要这个:

select * from messages 
where
id > (select coalesce(max(id), 0) from messages  where state <> 'error')
and
subscription_id = 1

假设id是唯一的(PK?)列,更高的id表示最新记录。

修改

这是正确的,正如@Marth所提到的,可能你需要在子查询中添加... AND subscription_id = 1

答案 1 :(得分:2)

无需PARTITION BY state,您希望SELECT行之后的所有行(created_at ASC顺序)为error,即bool_and(state = 'error')为{ {1}}:

true

编辑:根据预期结果,您可能需要在窗口函数中使用SELECT * FROM ( SELECT *, bool_and(state = 'error') OVER (ORDER BY created_at DESC, id) AS only_errors_afterward FROM sub ) s WHERE only_errors_afterward ; ┌────┬─────────────────┬───────┬───────────────────────────────┬────┬───────────────────────┐ │ id │ subscription_id │ state │ created_at │ ok │ only_errors_afterward │ ├────┼─────────────────┼───────┼───────────────────────────────┼────┼───────────────────────┤ │ 5 │ 1 │ error │ 2015-07-01 22:50:02.356113+02 │ f │ t │ │ 4 │ 1 │ error │ 2015-06-30 22:50:06.067279+02 │ f │ t │ └────┴─────────────────┴───────┴───────────────────────────────┴────┴───────────────────────┘ (2 rows)