在以下场景中,获得访问之间的平均距离的最简单方法是什么。
declare @LocationID int = 1;
declare @Visits table (
UserID int,
LocationID int,
DateTimeIn datetime,
DateTimeOut datetime
)
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (1, 1, '20150119 00:30', '20150119 00:45');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (1, 1, '20150119 00:50', '20150119 01:15');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (1, 1, '20150119 01:30', '20150119 02:00');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (1, 1, '20150119 02:05', '20150119 02:20');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (1, 1, '20150119 03:10', '20150119 03:15');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (2, 1, '20150119 00:32', '20150119 00:37');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (2, 1, '20150119 00:40', '20150119 00:55');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (2, 1, '20150119 01:53', '20150119 02:00');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (2, 1, '20150119 02:01', '20150119 02:15');
insert into @Visits (UserID, LocationID, DateTimeIn, DateTimeOut) values (2, 1, '20150119 03:10', '20150119 03:15');
我猜是这样的:
WITH CTE as (
select UserID, DateTimeIn, DateTimeOut, RANK() OVER (PARTITION BY UserID ORDER BY DateTimeIn asc) as 'RankNo'
from @Visits
)
Select AVG(Seconds) as 'AvgRecency' From (
SELECT A.UserID, ISNULL(DATEDIFF(SECOND, A.DateTimeOut, B.DateTimeIn), 0) as 'Seconds'
FROM CTE A INNER JOIN
CTE B on A.RankNo = B.RankNo-1 AND A.UserID = B.UserID
)A
但在实际程序中,即使存在包含userid和datetimein的索引,使用此方法也会导致排序操作出现溢出级别一级警告。
在没有排名功能的情况下还有其他方法吗?
答案 0 :(得分:1)
如果您使用的是SQL SERVER 2012+,则可以尝试使用LEAD
功能:
;WITH CTE AS (
SELECT UserID, DateTimeOut, LEAD(DateTimeIn) OVER (PARTITION BY UserID ORDER BY DateTimeIn asc) as 'NextCheckIn'
FROM @Visits
)
Select AVG(Seconds) as 'AvgRecency' From (
SELECT UserID, ISNULL(DATEDIFF(SECOND, DateTimeOut, NextCheckIn), 0) as 'Seconds'
FROM CTE
WHERE NextCheckIn IS NOT NULL
) A