Sql 用最小值对连续记录进行计数和求和

Sql 用最小值对连续记录进行计数和求和,sql,sql-server,sql-server-2014-express,Sql,Sql Server,Sql Server 2014 Express,我有一张表,显示了按月份汇总的客户付款情况。看起来是这样的: Client | Month1 | Month2 | Month3 | Month4 | Month5 | Month6 ------------------------------------------------------------ x1 | 100 | 200 | NULL | 100 | 100 | 100 x2 | 100 | 200 | NULL |

我有一张表,显示了按月份汇总的客户付款情况。看起来是这样的:

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,直到第一个没有付款的休息月。

也许有一些奇特的方法可以做到这一点,但我现在看不到

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

只要达到null,案例就会结束


试试下面的脚本。它有点长,你可以重写得更好

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

Aツ's的答案非常非常好,但申请完全没有必要。只需使用子查询或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;

David,谢谢你的编辑,我不知道如何设置表格的格式。我原来的源表格只是一个有金额和日期的大表格。我已按月份对金额进行了汇总和分组。我可以过滤掉过去3个月没有付款的所有客户,但除此之外,我甚至不知道从哪里开始。也许要计算连续月份的数量,然后以某种方式使用该数字。我喜欢这种逻辑,但应用是完全不必要的。@GordonLinoff交叉应用和cte得到相同的执行计划。这在计算连续付款时做到了。我用@daniel lower脚本总结了这一切。谢谢,这解决了我当前的问题。我将不得不查看上面的脚本,看看如何概括查询,因为它在未来将被更多地使用,连续月份的计数不总是3,我检查数据的月份也不总是6。如果我要做24个月的计算,这个例子会变得非常大。实际上,你可以首先理解第一个脚本的想法,你可以将这个想法应用到原始数据中。一个技巧是,如果可能的话,你可以使用临时表或变量表来存储中间数据,这可能会缩短脚本。谢谢你的建议。
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
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;