在 SQL 服务器中查找日期之间的间隔

Finding the interval between dates in SQL Server

我有一个 table 包括超过 500 万行的销售交易。我想找到 每个客户最近三笔购买之间的日期间隔总和

假设我的 table 看起来像这样:

CustomerID        ProductID             ServiceStartDate     ServiceExpiryDate     
   A                X1                     2010-01-01             2010-06-01
   A                X2                     2010-08-12             2010-12-30
   B                X4                     2011-10-01             2012-01-15
   B                X3                     2012-04-01             2012-06-01
   B                X7                     2012-08-01             2013-10-01
   A                X5                     2013-01-01             2015-06-01

我正在寻找的结果可能如下所示:

CustomerID        IntervalDays 
    A                  802
    B                  135               

我知道查询需要先检索每个客户的3次重发交易(基于ServiceStartDate),然后计算[=26=的startDateExpiryDate之间的间隔】 交易。

假设没有重叠,我想你想要这个:

select customerId,
       sum(datediff(day, ServiceStartDate, ServieEndDate) as Intervaldays
from (select t.*, row_number() over (partition by customerId
                                     order by ServiceStartDate desc) as seqnum
      from table t
     ) t
where seqnum <= 3
group by customerId;

试试这个:

SELECT dt.CustomerID,
        SUM(DATEDIFF(DAY, dt.PrevExpiry, dt.ServiceStartDate)) As IntervalDays
FROM (
    SELECT *
            , ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY ServiceStartDate DESC) AS rn
            , (SELECT Max(ti.ServiceExpiryDate) 
               FROM yourTable ti 
               WHERE t.CustomerID = ti.CustomerID 
                 AND ti.ServiceStartDate < t.ServiceStartDate) As PrevExpiry
    FROM yourTable t )dt
GROUP BY dt.CustomerID

结果将是:

CustomerId | IntervalDays
-----------+--------------
A          | 805
B          | 138

您想根据降序计算上一行的 ServiceExpiryDate 和当前行的 ServiceStartDate 之间的差异,然后将最后两个差异相加:

with cte as
 (
   select tab.*, 
      row_number()
      over (partition by customerId
            order by ServiceStartDate desc
                   , ServiceExpiryDate desc -- don't know if this 2nd column is necessary 
           ) as rn
   from tab
 ) 
select t2.customerId,
   sum(datediff(day, prevEnd, ServiceStartDate)) as Intervaldays
   ,count(*) as purchases
from cte as t2 left join cte as t1
on t1.customerId = t2.customerId
and t1.rn = t2.rn+1     -- previous and current row
where t2.rn  <= 3       -- last three rows
group by t2.customerId;

使用 LEAD 的相同结果:

with cte as
 (
   select tab.*, 
      row_number()
      over (partition by customerId
            order by ServiceStartDate desc) as rn
     ,lead(ServiceExpiryDate)
      over (partition by customerId
            order by ServiceStartDate desc
            ) as prevEnd
   from tab
 ) 
select customerId,
   sum(datediff(day, prevEnd, ServiceStartDate)) as Intervaldays
   ,count(*) as purchases
from cte 
where rn <= 3
group by customerId;

两者都不会 return 预期的结果,除非您从 Intervaldays 中减去 purchases(或 max(rn))。但是因为你只总结了两个差异,这对我来说似乎也不正确......

必须根据您的规则应用其他逻辑:

  • 客户的购买次数少于 3 次
  • 重叠间隔