我有一个用户列表,他们支持他们的账单,我想为他们每个人创建一个条目,说明他们已经落后了多少连续账单。所以这是表格:
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)
如果我理解正确的问题,首先你需要找到任何给定客户支付账单的最后日期,以便他们的未结余额为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
由于我们使用distinct,因此您不需要group by子句。
答案 1 :(得分: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