我需要从2个表(1个登录日志和1个注销日志)计算持续时间,每个表记录操作的日期时间和与之关联的accountID。目的是查看每个帐户在相应的登录和登录之间登录了多长时间。登出。表格架构如下(因为这是我的第一个帖子,如果格式错误,请道歉。)
UserLogInLog_201307
- DATETIME,datetime,not null
- AccountID,int,not null
UserLogOutLog_201307
- DATETIME,datetime,not null
- AccountID,int,not null
假设时间段为2013-07-17至2013-07-23。
我知道我应该使用DATEDIFF进行计算,但困难的部分是按相应的顺序配对每次登录和注销,并避免因拆分日登录或注销造成的混乱(即如果在2013年登录的帐户 - 07-12&退出2013-07-13)。
我最初的解决方案是使用AccountID& amp;分区。按DATETIME排名作为每一对的“锚”,然后我意识到由于分裂日的混乱而错了。
此外,我只对数据库具有只读权限,因此无法创建新的表/函数等。
有人可以给我一个解决方案吗?非常感谢你提前。
这是我的初始代码(不正确)供您参考:
-- RANK LOGOUT LOG BY LOGIN TIME
WITH cteLOGIN AS
(
SELECT AccountID
,[DATETIME] AS [LOGIN]
,RANK() OVER (PARTITION BY AccountID ORDER BY [DATETIME] ASC) AS [xRANK]
FROM [GameLog].[dbo].[UserLogInLog_201307]
WHERE DATETIME BETWEEN '2013-07-17' AND '2013-07-23'
)
-- RANK LOGOUT LOG BY LOGOUT TIME
,cteLOGOUT AS
(
SELECT AccountID
,[DATETIME] AS [LOGOUT]
,RANK() OVER (PARTITION BY AccountID ORDER BY [DATETIME] ASC) AS [xRANK]
FROM [GameLog].[dbo].[UserLogOutLog_201307]
WHERE DATETIME BETWEEN '2013-07-17' AND '2013-07-23'
)
-- COMBINE LOGIN & LOGOUT; MATCH RECORDS BY RANK #
SELECT A.AccountID
,AVG(DATEDIFF(MINUTE,A.LOGIN,B.LOGOUT)) AS AVG_TIME_DURATION
FROM cteLOGIN A JOIN cteLOGOUT B ON A.AccountID = B.AccountID
WHERE A.xRANK = B.xRANK
AND A.LOGIN < B.LOGOUT
GROUP BY A.AccountID
答案 0 :(得分:1)
我认为这里最好的方法是使用相关的子查询。
select ul.*, datediff(minute, datetime, logoutTime) as duration
from (select ulil.*,
(select top 1 ulol.datetime
from UserLogOutLog_201307 ulol
where ulil.AccountId = ulol.AccountId and
ulol.datetime > ulil.datetime
) as logoutTime
from UserLogInLog_201307 ulil
) ul;
然后,您可以过滤登录日期时间。
答案 1 :(得分:0)
我认为最好的方法是组合表格(不用担心,我不会要求你改变架构)。这是一个查询,可以生成表格的视图,其中有单独的开始和结束时间:
;WITH Unioned as
(
select [AccountID] id, [DATETIME] dt, 'in' thing from UserLogInLog_201307
union
select [AccountID] id, [DATETIME] dt, 'out' thing from UserLogOutLog_201307
)
,Combined as
(
select id, dt StartDt, LEAD(dt) OVER (PARTITION BY id ORDER BY dt) EndDt, thing
from Unioned
)
SELECT * from Combined
WHERE 1=1
AND thing = 'in' AND EndDt IS NOT NULL /*only use rows where the current action is 'login' and there is a corresponding logout time*/
AND StartDt >= '2013-01-01 00:15' and EndDt <= '2013-01-03'
现在你应该可以使用它来通过AccountID进行分组并获取平均日期值。