用户访问之间的平均距离

时间:2015-01-19 16:15:44

标签: sql sql-server

在以下场景中,获得访问之间的平均距离的最简单方法是什么。

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的索引,使用此方法也会导致排序操作出现溢出级别一级警告。

在没有排名功能的情况下还有其他方法吗?

1 个答案:

答案 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