在 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=的startDate
和ExpiryDate
之间的间隔】 交易。
假设没有重叠,我想你想要这个:
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 次
- 重叠间隔
我有一个 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=的startDate
和ExpiryDate
之间的间隔】 交易。
假设没有重叠,我想你想要这个:
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 次
- 重叠间隔