我目前有一个MS SQL查询,用于计算每个用户在一天内登录系统的时间长度。我从记录中提取此信息的表每个都作为单独的记录登录/注销。目前,我的MS SQL代码如下:
SELECT
CAST(DateTime As Date),
UserID,
MIN(DateTime),
MAX(DateTime),
DATEDIFF(SS, MIN(DateTime), MAX(DateTime))
FROM
LoginLogoutData
WHERE
CAST(DateTime AS DATE) = '01/01/2015'
GROUP BY
CAST(DateTime As Date),
UserID
这可以根据需要运行,并创建一个类似于下面的表。
Date UserID FirstLogIn FinalLogOut LoggedInTime
......... ...... .......... ............ ............
01/01/2015 ABC 07:42:57 14:57:13 26056
01/01/2015 DEF 07:45:49 13:57:56 22326
这适用于一天的数据。但是,如果我想计算某人在更大的日期范围内登录系统的时间长度,例如一个星期或一个月,这不起作用;它会计算用户在第一天登录和退出最后一天之间的时间长度。
基本上,我希望我的代码计算(Max(DateTime) - Min(DateTime))
FOR EACH DAY ,然后将所有这些值合并为一个仅由UserId
分组的简单表格。然后,我可以随意设置我的日期范围,并收到正确的结果。
所以我的表格如下:
UserId LoggedInTime
........ .............
ABC 563287
DEF 485823
GEH 126789
我认为我需要在GROUP BY
函数中使用MIN()
,但我还没有太多经验。
有没有人有这方面的经验?任何帮助将不胜感激。
谢谢。
答案 0 :(得分:1)
首先,您需要按日期汇总,然后按较大的时间单位汇总。例如,今年迄今为止:
SELECT UserId, SUM(diffsecs)
FROM (SELECT CAST(DateTime As Date) as thedate, UserID,
DATEDIFF(second, MIN(DateTime), MAX(DateTime)) as diffsecs
FROM LoginLogoutData
GROUP BY CAST(DateTime As Date), UserID
) ud
WHERE thedate between '2015-01-01' and getdate();
答案 1 :(得分:0)
由于您已经为每个日期计算LoggedInTime
,因此需要进行以下查询
SELECT USERID,SUM(LoggedInTime) LoggedInTime
FROM YOURTABLE
GROUP BY USERID
<强>更新强>
由于您有一条登录记录和下一条登出记录(无论日期如何),我们可以使用SELF JOIN(一个连接自身的表)的概念来获取相应登录时间的注销日期时间。
DECLARE @FROMDATE DATETIME='2014-01-01 07:42:57.000'
DECLARE @TODATE DATETIME='2015-02-01 07:42:57.000'
;WITH CTE AS
(
-- ROW_NUMBER() is taken as logic for self joining.
SELECT ROW_NUMBER() OVER(ORDER BY USERID,[DATETIME]) RNO,*
FROM #TEMP
WHERE [DATETIME] >= @FROMDATE AND [DATETIME] < @TODATE
)
,CTE2 AS
(
-- Since we are using SELF JOIN,we will get the next row's
-- datetime(ie, Logout time for corresponding login time)
SELECT C1.*,C2.[DATETIME] [DATETIME2],
DATEDIFF(SS, C1.[DateTime], C2.[DateTime]) SECONDSDIFF
FROM CTE C1
LEFT JOIN CTE C2 ON C1.RNO=C2.RNO-1
WHERE C1.RNO%2 <> 0
-- Since we get the next row's datetime in current row,
-- we omit each logout time's row
)
SELECT USERID,SUM(SECONDSDIFF) SECONDSDIFF
FROM CTE2
答案 2 :(得分:0)
您可以对第一个查询使用另一个group by语句,如下所示:
Select UserID,SUM(LoggedTime)
FROM
(
SELECT CAST(DateTime As Date),
UserID, MIN(DateTime),
MAX(DateTime),
DATEDIFF(SS, MIN(DateTime), MAX(DateTime)) AS LoggedTime
FROM LoginLogoutData
WHERE CAST(DateTime AS DATE) = '01/01/2015'
GROUP BY CAST(DateTime As Date), UserID
) As temp
GROUP BY UserID
您可以在此处更改where子句以匹配数据范围。它将首先计算每天的记录时间,然后获得每个用户所有天数的总和。
答案 3 :(得分:0)
以下是如何使用工作示例数据和包含的T-SQL执行此操作的示例。
-- original table you described
CREATE TABLE LoginLogoutData (UserID int, DateTime DateTime)
GO
-- clean any previous sample records
TRUNCATE TABLE LoginLogOutData
/*local variables for iteration*/
DECLARE @i int = 1
DECLARE @n int
DECLARE @entryDate DateTime = GETDATE()
--populate the table with some sample data
/* for each of the five sample users, generate sample login and logout
data for 30 days. Each login and logout are simply an hour apart for demo purposes. */
SET NOCOUNT ON
-- iterate over 5 users (userid)
WHILE (@i <= 5)
BEGIN
--set the initial counter for the date loop
SET @n = 1
--dated entry loop
WHILE (@n <= 30)
BEGIN
-- increment to the next day
SET @entryDate = DateAdd(dd,@n,GETDATE())
--logged in entry
INSERT INTO LoginLogoutData (DateTime, UserID)
SELECT @entryDate,@i
-- logged out entry
INSERT INTO LoginLogoutData (DateTime, UserID)
SELECT DateAdd(hh,1,@entryDate),@i
--increment counter
SET @n = @n+1
END
--increment counter
SET @i=@i+1
END
GO
/* demonstrate that for each user each day has entries and that
the code calculates (Max(DateTime) - Min(DateTime)) FOR EACH DAY
*/
SELECT UserID,
MIN(DateTime) AS LoggedIn,
MAX(DateTime) AS LoggedOut,
DATEDIFF(SS, MIN(DateTime), MAX(DateTime)) AS LoginTime
FROM LoginLogoutData
GROUP BY CAST(DateTime As Date), UserID
/*this is a table variable used to support the "sum all these values together into one
simple table grouped only by UserId*/
DECLARE @SummedUserActivity AS TABLE (UserID int, DailyActivity int)
-- group the subtotals from each day per user
INSERT INTO @SummedUserActivity (UserID, DailyActivity)
SELECT UserID, DATEDIFF(SS, MIN(DateTime), MAX(DateTime))
FROM LoginLogoutData
GROUP BY CAST(DateTime As Date), UserID
-- demonstrate the sum of the subtotals grouped by userid
SELECT UserID, SUM(DailyActivity) AS TotalActivity
FROM @SummedUserActivity
GROUP BY UserID