计算并求和具有最小值的连续记录

Count and Sum consecutive records with minimum value

我有一个 table 显示按月汇总的客户付款。它看起来像这样:

Client | Month1 | Month2 | Month3 | Month4 | Month5 | Month6  
------------------------------------------------------------
x1     | 100    | 200    | NULL   | 100    | 100    | 100  
x2     | 100    | 200    | NULL   | NULL   | 100    | 100  
x3     | NULL   | NULL   | 200    | 100    | 100    | 100  
x4     | NULL   | 200    | 300    | 100    | 100    | NULL  
x5     | 100    | 200    | 200    | 100    | 100    | 100  
x6     | NULL   | NULL   | NULL   | 100    | 100    | 100  
x7     | NULL   | 200    | 300    | 100    | 100    | 100  
x8     | NULL   | 200    | NULL   | 100    | 100    | NULL  

我需要汇总连续付款的值,其中连续付款的次数为>=3,间隔从上个月开始倒推。

所以应该总结所有有第 6、5 和 4 个月的人以及那些连续付款延伸到过去的人。考虑到这一点,从上面的例子来看,客户 1、3、5、6 和 7 应该在里面,对他们来说,总和应该是:

X1 - Last 3 months  
X3 - Last 4 months  
X5 - Last 6 months  
X6 - Last 3 Months  
X7 - Last 5 months

所以从最后一个月到过去的所有月份,其中连续的是 >=3,直到第一次休息(没有付款的月份)。

也许有一些奇特的方法可以做到,但我目前还没有看到。

我会选择外部应用,因为您想使用计算列两次。

只要达到 nullcase 就会结束。

select *
from data
cross apply (
   select cnt = case when month6 is null then 0
                     when month5 is null then 1
                     when month4 is null then 2
                     when month3 is null then 3
                     when month2 is null then 4
                     when month1 is null then 5
                end
)
where cnt>=3

试试下面的脚本。有点长,大家可以重写一下。

select p1.Client, sum(p1.Amount) Amount
from
(
    select Client, MonthName, Amount
    from
    (
        select
            Client,
            isnull(Month1, 0) Month1,
            isnull(Month2, 0) Month2,
            isnull(Month3, 0) Month3,
            isnull(Month4, 0) Month4,
            isnull(Month5, 0) Month5,
            isnull(Month6, 0) Month6
        from Payment
    ) pm
    unpivot
    (
        Amount
        for MonthName in (Month1, Month2, Month3, Month4, Month5, Month6)
    ) unpvt
) p1
left join
(
    -- get last month with null value
    select Client, max(MonthName) MonthName
    from
    (
        select
            Client,
            isnull(Month1, 0) Month1,
            isnull(Month2, 0) Month2,
            isnull(Month3, 0) Month3,
            isnull(Month4, 0) Month4,
            isnull(Month5, 0) Month5,
            isnull(Month6, 0) Month6
        from Payment
    ) pm
    unpivot
    (
        Amount
        for MonthName in (Month1, Month2, Month3, Month4, Month5, Month6)
    ) unpvt
    where unpvt.Amount = 0
    group by unpvt.Client

) p2 on p2.Client = p1.Client and p1.MonthName <= p2.MonthName
where p2.Client is null
group by p1.Client
having count(p1.Client) >= 3

上面的脚本可以通过having子句控制连续月份的计数,比较通用。下面的脚本更具体。

select Client, sumpayment.Amount
from
(
    select
    Client,
    case
    when Month6 is null or Month5 is null or Month4 is null then 0
    when Month3 is null then Month6 + Month5 + Month4
    when Month2 is null then Month6 + Month5 + Month4 + Month3
    when Month1 is null then Month6 + Month5 + Month4 + Month3 + Month2
    else Month6 + Month5 + Month4 + Month3 + Month2 + Month1
    end as Amount
    from Payment
) sumpayment
where sumpayment.Amount > 0

阿ツ的回答非常非常好,但是apply完全没有必要。只需使用子查询或 CTE:

select d.*
from (select d.*,
             (case when month6 is null then 0
                   when month5 is null then 1
                   when month4 is null then 2
                   when month3 is null then 3
                   when month2 is null then 4
                   when month1 is null then 5
              end) as cnt
      from data d
     ) d
where cnt >= 3;