2016-08-24 37 views
2

如果我有如下表:如何計算某個值之前有多少行?

CREATE TABLE test (
     c_id INTEGER, 
     ref_date DATE, 
     success BOOLEAN 
); 

INSERT INTO test 
VALUES 
(8, '2016-01-01', FALSE), 
(8, '2016-01-04', TRUE), 
(8, '2016-01-07', FALSE), 
(8, '2016-01-09', FALSE), 
(8, '2016-01-15', TRUE), 
(9, '2016-01-05', TRUE) 
; 

我想建立一個返回下面的查詢:

8, '2016-01-01', FALSE, 
8, '2016-01-04', TRUE, 2 
8, '2016-01-07', FALSE, 
8, '2016-01-09', FALSE, 
8, '2016-01-15', TRUE, 3 
9, '2016-01-05', TRUE, 1 

我想要做的是,爲每個C_ID,爲了通過日期,然後爲成功列中的每個TRUE值計算自該第一行到該c_id或最後一個TRUE值以來的行數。因此,在示例輸出中,第二行有兩個,因爲當ref_dates被排序時,第一個TRUE值是該組c_id開始以來的第二行。第二行到最後一行有一個3,因爲它是TRUE,並且是自上一個TRUE值起的第三行。

我在努力計算需要多少推薦才能獲得成功的推薦。

我原本以爲我可以使用lag()窗口函數來構建查詢,但是沒有辦法將最後一行的上一個邊界設置爲成功屬性的TRUE值。

如何計算某個值之前有多少行?

我正在運行PostgreSQL 9.5。

回答

3

我有一種感覺,這可以進一步簡化,但此查詢將工作使用:

  • lag到標誌,是一個不同的邏輯分組的開始行
  • 累計sum標記所有的相同的邏輯分組的行具有唯一分組標識
  • count使得由邏輯分組ID分區

查詢:

with grp_start_cte as (
    select *, 
     coalesce(lag(success) over (partition by c_id order by ref_date), true) as is_grp_start 
    from test 
), grp_cte as (
    select *, 
     sum(case when is_grp_start then 1 else 0 end) over (partition by c_id order by ref_date) as grp_id 
    from grp_start_cte 
) 
select c_id, ref_date, success, 
     case when success then count(*) over (partition by c_id, grp_id) end as cnt 
    from grp_cte 
order by c_id, ref_date 
+0

與lag()的結果sum()的位是我的嘗試失蹤。那是一個聰明的作品;感謝您的幫助。 –

相關問題