按列和日期范围获取最大行数

时间:2017-04-28 18:51:55

标签: sql tsql

我试图根据列和另一列的日期范围获取唯一的行列表。以下是示例数据:

billing.Text = "$" + ds.Tables[0].Rows[0]["Billing"].ToString();

我需要按CustomerNum分组,然后按ServiceDate进行分组,但仅限于ServiceDate在7天内。我希望通过分组获得最大(最新)行。所以结果应该是:

id      CustomerNum    ServiceDate
------------------------------------------------
4406290 000000000066    2017-02-17 13:03:00.000
4406294 000000000066    2017-02-17 13:07:00.000
4406295 000000000066    2017-02-17 13:09:00.000
4406295 000000000066    2017-02-09 13:09:00.000
4406352 000000000066    2017-01-17 13:12:00.000
4406369 000000000066    2017-03-17 13:16:00.000
4582381 000000ABC102    2016-03-22 14:48:00.017
4589037 000000ABC102    2016-07-23 14:54:11.223
4625101 000009983148    2017-03-30 15:21:11.283
4625162 000005555398    2017-01-30 11:22:20.907
4625165 000005555398    2017-03-30 12:22:20.907
4625168 000005555398    2017-03-30 15:22:20.907

我尝试过以下方法:

id      CustomerNum    ServiceDate
------------------------------------------------
4406295 000000000066    2017-02-17 13:09:00.000
4406295 000000000066    2017-02-09 13:09:00.000
4406352 000000000066    2017-01-17 13:12:00.000
4406369 000000000066    2017-03-17 13:16:00.000
4582381 000000ABC102    2016-03-22 14:48:00.017
4589037 000000ABC102    2016-07-23 14:54:11.223
4625101 000009983148    2017-03-30 15:21:11.283
4625162 000005555398    2017-01-30 11:22:20.907
4625168 000005555398    2017-03-30 15:22:20.907

但这会在所有CustomerNum上给出行号,而不是在满足日期范围后在1处开始行号。

我知道我错过了什么。有什么想法吗?谢谢。

1 个答案:

答案 0 :(得分:2)

对于此问题,您希望使用lag()和累计总和。使用滞后来确定每个组的起始位置,然后使用累计和来分配组:

select sum(case when prev_ServiceDate > dateadd(day, -7, ServiceDate) then 0 else 1 end) over
           (partition by CustomerNum order by ServiceDate) as grp
from (select ct.*, 
             lag(ServiceDate) over (partition by CustomerNum order by ServiceDate) as prev_ServiceDate
      from CustomerTransactions ct
     ) ct;

然后,您可以使用聚合汇总组:

select CustomerNum, min(ServiceDate), max(ServiceDate)
from (select sum(case when prev_ServiceDate > dateadd(day, -7, ServiceDate) then 0 else 1 end) over
                 (partition by CustomerNum order by ServiceDate) as grp
      from (select ct.*, 
                   lag(ServiceDate) over (partition by CustomerNum order by ServiceDate) as prev_ServiceDate
            from CustomerTransactions ct
           ) ct
     ) ct
group by CustomerNum, grp