2017-06-13 30 views
1

考慮下面的數據結構相匹配:選擇直到行中的Postgres

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 

在查找不同狀態並匹配上面僅示例的第4和5位頂部的示例後,如何進行查詢以「停止」?

+0

如果你也有1行('id = 6'和'state = sent'),那麼結果是什麼?與問題相同? –

+0

好問題。它根本不應該返回任何行。 – Martin

回答

2

如果我理解正確的,你需要這樣的:

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

假設id是唯一的(?PK)列和更高的ID表示最新的記錄。

編輯

那是正確的,因爲@Marth提到,可能需要在子查詢

+0

有趣的方法,但它返回'(0行)'。 – Martin

+0

根據您提供的示例數據,這應該返回2個最後記錄(id 4和5) –

+2

@OtoShavadze:在子查詢中可能缺少'AND subscription_id = 1'(例如,如果訂閱2具有id = 6 AND狀態='成功')。 – Marth

2

添加... AND subscription_id = 1無需PARTITION BY state,要SELECT行,其中的所有行之後(在created_at ASC順序)是error,即bool_and(state = 'error')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) 

編輯:根據預期的結果,您可能需要在窗口功能PARTITION BY subscription_id