2014-10-28 47 views
1

考慮下表:PostgreSQL的 - 在一系列檢測模式

id | date  | status 
1 | 2014-01-10 | 1 
1 | 2014-02-10 | 1 
1 | 2014-03-10 | 1 
1 | 2014-04-10 | 1 
1 | 2014-05-10 | 0 
1 | 2014-06-10 | 0 
------------------------ 
2 | 2014-01-10 | 1 
2 | 2014-02-10 | 1 
2 | 2014-03-10 | 0 
2 | 2014-04-10 | 1 
2 | 2014-05-10 | 0 
2 | 2014-06-10 | 0 
------------------------ 
3 | 2014-01-10 | 1 
3 | 2014-02-10 | 0 
3 | 2014-03-10 | 0 
3 | 2014-04-10 | 1 
3 | 2014-05-10 | 0 
3 | 2014-06-10 | 0 
------------------------ 
4 | 2014-01-10 | 0 
4 | 2014-02-10 | 1 
4 | 2014-03-10 | 1 
4 | 2014-04-10 | 1 
4 | 2014-05-10 | 0 
4 | 2014-06-10 | 0 
------------------------ 
5 | 2014-01-10 | 0 
5 | 2014-02-10 | 1 
5 | 2014-03-10 | 0 
5 | 2014-04-10 | 1 
5 | 2014-05-10 | 0 
5 | 2014-06-10 | 0 
------------------------ 

的ID字段是用戶ID,日期字段當某一關卡是由於和狀態指示,如果檢查點被完成它的用戶。

我在嘗試檢測跳過某些檢查點的用戶時遇到了很大的麻煩,例如用戶使用了標識爲2,3,4和5的標記。實際上,我需要一個查詢來列出在中間缺少檢查點的標識或系列的開始,只返回id。

我努力找到一種方法,只是用查詢做到這一點,但我無法創建一個。我知道我可以編寫一些腳本,但是我正在處理的那個項目需要我使用SQL來完成。

任何人對如何實現這一點都有絲毫的想法?

編輯:所推薦的器官功能障礙綜合徵這裏有更多的細節,有些事情我沒有成功嘗試:

我最成功的嘗試是計算有多少狀態被註冊爲使用此查詢每個ID:

SELECT 
    id, 
    SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS check, 
    SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS non_check 
FROM 
    example_table 
GROUP BY 
    id 
ORDER BY 
    id 

得到以下結果:

id | check | non_check 
1 | 4  | 2 
2 | 3  | 3 
3 | 2  | 4 
4 | 3  | 3 
5 | 2  | 4 

與導致我可以選擇每個ID限條目通過它的檢查結果的統計做算術我們實地,如果SUM結果與檢查結果相等,則該檢查站是連續的,就像在:

WITH tbl AS (
    SELECT id, status, SUM(status) AS "sum" 
    FROM (
      SELECT id, status FROM example_table WHERE id = 1 ORDER BY date LIMIT 4 
     ) AS tbl2 
    GROUP BY 
      status,id 
) 
SELECT 
    id,"sum" 
FROM 
    tbl 
WHERE 
    status = 1 

得到以下結果:

id | sum 
1 | 4 

由於總和結果等於檢查第一個查詢,我可以確定檢查點是連續的。而是採取ID 2爲例這個時候,它的查詢是:

WITH tbl AS (
    SELECT id, status, SUM(status) AS "sum" 
    FROM (
      SELECT id, status FROM example_table WHERE id = 2 ORDER BY date LIMIT 3 
     ) AS tbl2 
    GROUP BY 
      status,id 
) 
SELECT 
    id,"sum" 
FROM 
    tbl 
WHERE 
    status = 1 

請注意,我改變了WHERE和基於我的工作,其ID並在首次檢查結果的極限值上的ID查詢,我得到了以下結果:

id | sum 
2 | 2 

至於ID 2在該查詢總和字段值從它的校驗值不同,我可以說這是不連續的。每個ID都可以重複該模式。

正如我之前所說的那樣,爲了解決這個問題,我需要通過代碼來實現,但是在特定情況下,我需要它在SQL中。

而且我發現下面的文章:

postgres detect repeating patterns of zeros

在這問題就像我的,但他要檢測重複零,它具有賜教了一點,但還不足以解決我自己的問題。

在此先感謝!

+0

歡迎堆棧溢出。這不是在這裏提出問題的好方法。你有沒有嘗試解決你的問題?首先顯示你的努力,以便人們可以展示他們的努力請閱讀[常見問題](http://stackoverflow.com/tour),[如何問](http://stackoverflow.com/help/how-to-ask)和[幫助中心](http:// stackoverflow .com/help)作爲開始。 – 2014-10-28 14:31:10

+0

感謝您的建議Nahuel Ianni!也許這種方式更好! – 2014-10-28 16:50:21

+0

現在好多了:)代碼+1。 – 2014-10-28 17:46:03

回答

1

您正在尋找的模式是錯過的檢查點,然後是完成的檢查點。加入從與下一個(由時間戳)檢查站用戶的每個關卡然後查找狀態0連接到狀態1。

下面是一個例子:

create table tab (id int,date date,status int); 
insert into tab values(1 , '2014-01-10' , 1),(1 , '2014-02-10' , 1),(1 , '2014-03-10' , 1),(1 , '2014-04-10' , 1),(1 , '2014-05-10' , 0),(1 , '2014-06-10' , 0),(2 , '2014-01-10' , 1),(2 , '2014-02-10' , 1),(2 , '2014-03-10' , 0),(2 , '2014-04-10' , 1),(2 , '2014-05-10' , 0),(2 , '2014-06-10' , 0),(3 , '2014-01-10' , 1),(3 , '2014-02-10' , 0),(3 , '2014-03-10' , 0),(3 , '2014-04-10' , 1),(3 , '2014-05-10' , 0),(3 , '2014-06-10' , 0),(4 , '2014-01-10' , 0),(4 , '2014-02-10' , 1),(4 , '2014-03-10' , 1),(4 , '2014-04-10' , 1),(4 , '2014-05-10' , 0),(4 , '2014-06-10' , 0),(5 , '2014-01-10' , 0),(5 , '2014-02-10' , 1),(5 , '2014-03-10' , 0),(5 , '2014-04-10' , 1),(5 , '2014-05-10' , 0),(5 , '2014-06-10' , 0); 
with tabwithrow as 
    (select * 
      , row_number() OVER(PARTITION by id order by date) rnum 
     from tab) 
select * 
from tabwithrow a 
join tabwithrow b on b.rnum = a.rnum + 1 
     and a.id = b.id 
     and a.status = 0 
     and b.status = 1; 
+0

對不起,如果我聽起來啞巴,但我怎麼能這樣做? – 2014-10-28 17:06:28

+0

SQL小提琴當前處於關閉狀態。我會提供一個演示,當它回來 – Andreas 2014-10-28 17:16:28

+0

@TiagoRatto更新 – Andreas 2014-10-28 17:40:25