计算行直到where子句条件满足为止

时间:2016-02-15 13:58:43

标签: sql postgresql

我有一个数据表,其中包含body,offer_id和created_at等属性。按时间顺序,我需要找到行数,直到'body'满足特定offer_id的'where'子句,即

created at | offer id | body
---------------------------------------------
Jan        | 12       | does not satisfy
Feb        | 12       | does not satisfy
Mar        | 12       | satisfies
Jan        | 13       | does not satisfy
Feb        | 13       | satisfies
Jan        | 14       | does not satisfy
Feb        | 14       | satisfies
Mar        | 14       | does not satisfy
Apr        | 14       | does not satisfy

预期产出:

offer_id | count
---------|------
12       | 3
13       | 2
14       | 2

7 个答案:

答案 0 :(得分:1)

首先 - 您需要为其商品窗口中的每条记录生成一个数字:

select t.*, rownumber() over (partition by t.offer_ID order by t.created_at) as rn
from t

它将导致类似:

created at | offer id | body             | rn
---------------------------------------------
Jan        | 12       | does not satisfy | 1
Feb        | 12       | does not satisfy | 2
Mar        | 12       | satisfies        | 3
Jan        | 13       | does not satisfy | 1
Feb        | 13       | satisfies        | 2
Jan        | 14       | does not satisfy | 1
Feb        | 14       | satisfies        | 2
Mar        | 14       | does not satisfy | 3
Apr        | 14       | does not satisfy | 4

从这个子查询中你可以得到一个最小rn(满足条件的第一条记录):

with sub as (
    select t.*, rownumber() over (partition by t.offer_ID order by t.created_at) as rn
    from t)
select offer_ID, min(rn)
from sub
where (satisfies)
group by offer_ID

答案 1 :(得分:0)

你尝试过这样的事吗?

select count(*)
from mytable
where "satisfies"

或者,如果您只想计算不同的offer_id:

select count(distinct  offer_id)
from mytable
where "satisfies"

或者,最后:

select count(offer_id)
from mytable
where "satisfies"
group by offer_id

这是你需要的吗?如果没有,请给我更多细节! ;)

答案 2 :(得分:0)

计算不满足条件的数字的一种方法是使用累积总和:

select offer_id, count(*)
from (select t.*,
             sum(case when <condition> then 1 else 0 end) over
                 (partition by offer_id order by created_at) as num
      from t
     ) t
where num = 0;

然而,这比您的数字少一个。所以,相反:

select offer_id,
       (sum(case when num = 0 then 1 else 0 end) +
        max(case when num = 1 then 1 else 0 end)
       )
from (select t.*,
             sum(case when <condition> then 1 else 0 end) over
                 (partition by offer_id order by created_at) as num
      from t
     ) t
where num in (0, 1)

答案 3 :(得分:0)

如果您只想要offer_id的计数,可以使用以下

select offer_id, count(*) as count_1 from table_name
where <<your condition>>
group by offer_id

如果我的理解有误,请分享您需要的详细说明。

答案 4 :(得分:0)

您可以将任务分为两部分:

  1. 对于每个商品ID,找到首先满足条件的记录/日期。
  2. 计算每个商品ID的所有记录,直至找到记录/日期。
  3. 使用SELECT中的子查询:

    select 
      offer_id,
      (
        select count(*)
        from mytable m
        where m.offer_id = mfit.offer_id
        and m.created_at <= min(mfit.created_at)
      ) as cnt
    from mytable mfit
    where <condition>
    group by offer_id
    

    或FROM中的子查询:

    select
      mfit.offer_id, 
      count(*) as cnt
    from
    (
      select offer_id, min(created_at) as min_date
      from mytable
      where <condition>
      group by offer_id
    ) mfit
    join mytable m on m.offer_id = mfit.offer_id and m.created_at <= mfit.created_at
    group by mfit.offer_id;
    

答案 5 :(得分:0)

直视箭头

select t.offer_id, count(*)
from mytable t
where not exists
  (
    select 1 from mytable tt 
    where tt.offer_id = t.offer_id
      and tt.created_at < t.created_at
      and tt.body = 'satisfies'
  )
group by t.offer_id

答案 6 :(得分:0)

这是使用分析函数的另一个查询。分析函数的优势在于您只需读取一次表,即可获得不同的聚合。我们的想法是每个offer_id有一个运行总计,其中一个用于匹配条件的记录加上每个offer_id的计数。这看起来如下:

created at | offer id | body               | s | c
---------------------------------------------------
Jan        | 13       | does not satisfy   | 0 | 1
Feb        | 13       | satisfies          | 1 | 2
Jan        | 14       | does not satisfy   | 0 | 1
Feb        | 14       | satisfies          | 1 | 2
Mar        | 14       | does not satisfy   | 1 | 3
Apr        | 14       | does not satisfy   | 1 | 4
May        | 14       | satisfies          | 2 | 5
Jun        | 14       | does not satisfy   | 2 | 6
Apr        | 14       | does not satisfy   | 2 | 7
May        | 14       | satisfies          | 3 | 8

所以我们只是寻找s = 1的min(c)。

def reverse(text):
    length = len(text)
    a = ''
    for pos in range(length):
        a += text[length-pos-1]
    print a