2017-04-06 74 views
2

我已經列出了賬單背後的用戶列表,並且我想爲每個用戶生成一個條目,一直在後面。因此,這裏的表:計算滿足GROUP條件的連續條目的數量BY

user | bill_date | outstanding_balance 
--------------------------------------- 
a | 2017-03-01 |  90 
a | 2016-12-01 |  60 
a | 2016-09-01 |  30 
b | 2017-03-01 |  50 
b | 2016-12-01 |  0 
b | 2016-09-01 |  40 
c | 2017-03-01 |  0 
c | 2016-12-01 |  0 
c | 2016-09-01 |  1 

而且我要的查詢會產生如下表:

user | consecutive_billing_periods_behind 
----------------------------------------- 
    a |    3 
    b |    1 
    a |    0 

換句話說,如果你在任何時候繳納的,我想忽略所有之前的條目,並且只計算自您上次付款以來您一直支付的結算週期數。我如何最簡單地做到這一點?

回答

0

如果我理解正確的問題,首先你需要找到任何給定的客戶支付賬單所以最後日的餘額爲0。您可以通過此子查詢做到這一點的最後日期:

  (SELECT 
       user1, 
       bill_date AS no_outstanding_bill_date 
      FROM table1 
      WHERE outstanding_balance = 0) 

然後,您需要獲取最後的帳單日期併爲每一行創建字段(如果它們是未付帳單)。然後,通過該過濾器的最後一個晴朗的日子裏,以每個客戶的最後賬單日之間的行where子句:

WHERE bill_date >= last_clear_day AND bill_date <= last_bill_date 

然後,如果你把拼在一起,你可以通過這個查詢的結果:

SELECT 
    DISTINCT 
    user1, 
    sum(is_outstanding_bill) 
    OVER (
    PARTITION BY user1) AS consecutive_billing_periods_behind 
FROM (
     SELECT 
     user1, 
     last_value(bill_date) 
     OVER (
      PARTITION BY user1 
      ORDER BY bill_date 
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_bill_date, 
     CASE WHEN outstanding_balance > 0 
      THEN 1 
     ELSE 0 END             AS is_outstanding_bill, 
     bill_date, 
     outstanding_balance, 
     nvl(max(t2.no_outstanding_bill_date) 
      OVER (
       PARTITION BY user1), min(bill_date) 
      OVER (
       PARTITION BY user1))         AS last_clear_day 

     FROM table1 t1 
     LEFT JOIN (SELECT 
         user1, 
         bill_date AS no_outstanding_bill_date 
        FROM table1 
        WHERE outstanding_balance = 0) t2 USING (user1) 
    ) table2 
WHERE bill_date >= last_clear_day AND bill_date <= last_bill_date 

由於我們使用不同的你不需要group by子句。

0
select 
    user, 
    count(case when min_balance > 0 then 1 end) 
    as consecutive_billing_periods_behind 
from 
(
    select 
    user, 
    min(outstanding_balance) 
     over (partition by user order by bill_date) as min_balance 
    from tbl 
) 
group by user 

或者:

select 
    user, 
    count(*) 
    as consecutive_billing_periods_behind 
from 
(
    select 
    user, 
    bill_date, 
    max(case when outstanding_balance = 0 then bill_date) over 
     (partition by user) 
     as max_bill_date_with_zero_balance 
    from tbl 
) 
where 
    -- If user has no outstanding_balance = 0, then 
    max_bill_date_with_zero_balance is null 
    -- Count all rows in this case. 

    -- Otherwise 
    or 
    -- count rows with 
    bill_date > max_bill_date_with_zero_balance 
group by user