I am working on a project and have a table with the following data:
| date | time | username | type | session_time |
|---|---|---|---|---|
| 2023-08-28 | 07:56:50.0000000 | aavery35 | login | NULL |
| 2023-08-28 | 08:07:53.0000000 | aavery35 | view | NULL |
| 2023-08-28 | 08:08:48.0000000 | aavery35 | update | NULL |
| 2023-08-28 | 08:08:48.0000000 | aavery35 | update | NULL |
| 2023-08-28 | 08:08:48.0000000 | aavery35 | update | NULL |
I am trying to find a way to update the session_time variable to find where date = date and username = username then subtract logout:time - login:time
part of the problem is that every user does not necessarily have a logout time. In that instance i would like to go to their last action of that day and create a new row for that date, time, and username and create a logout instance.
I don't think this is possible with all the 'type' variables being in the same column. So instead i have created three new variables login_time, logout_time, session_time. I then ran the following code :
Alter Table ##remote_users
Add session_time date;
Alter Table ##remote_users
Add login_time time;
Alter Table ##remote_users
Add logout_time time;
Update ##remote_users
set login_time = time
where username = username AND date = date AND Type = 'login';
Update ##remote_users
set logout_time = time
where username = username AND date = date AND Type = 'logout';
Update ##remote_users
set session_time = login_time - logout_time
where username = username AND date = date;
select date, time, username, type, login_time, logout_time
from ##remote_users
WHERE type = 'login' OR type = 'logout' OR type = 'sessiontimeout'
order by username
This was close because it created the variables that i needed but the session_time update did not work it gave the following error:
Msg 8117, Level 16, State 1, Line 57
Operand data type time is invalid for subtract operator.
Additionally, users without a logout time get a null value for teh variable logout_time.
You can do something like this:
I wrote two versions, #1 is the simple one that takes min and max time to create logintimeNew and logoutTimeNew columns, and then does a time diff manipulation to create the "time" part of a session time.
This assumes that first date per day is login, and last day if logout. If you really want to find the "session time" parts, you can use the #2 version. That one does a conditional aggregation to find login / logout rows, and falls back to first / last rows if those are missing
To explain the details:
min(time) OVER(PARTITION BY username, date)is a window aggregation that calculates minumum time grouped (partitioned) by user and date. This helps us get the needed date values per day.CAST(dateadd(ms, datediff(ms, logintimenew, logouttimenew) , '19000101') AS TIME)this complex formula is to convert difference of two days in terms of "time" datatype. There's probably a better way, but this version calculates difference in milliseconds and then creates a date by adding milliseconds to the "zero date in sql server", which is 19000101. Then, by converting this to TIME, one gets the time part of the difference.