2016-08-24 51 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()的位是我的尝试失踪。那是一个聪明的作品;感谢您的帮助。 –

相关问题