I have a table that needs to be updated with the values from the same table. Basically, I want to change the connection setup in the rows where the worker and client are same and that the changed row Connection setup started in 5mins after the other connection (with the same worker and client) ended. The code below does this. But there is one more problem. when there are multiple connections that happen in short period of time, between the same client and worker I need them all to have the same Connection setup. I really am not sure how to achieve this.
the current query:
UPDATE t
SET t.[Connection setup] = t2.[Connection setup]
FROM Table1 t
INNER JOIN Table1 t2 ON t.worker = t2.worker
AND t.client = t2.client
AND t.SessionNo <> t2.SessionNo
AND t.[Connection setup] <= DATEADD(mi, 5, t2.[Connection end])
AND t.[Connection setup] >= t2.[Connection end]
As you can see in this example there are several connections between same client and worker and the column "real_time" shows what time they should have.
SessionNo worker Tag Start Ende Dauer Connection setup Connection end client right_time
5 116590 mma 09.08.2020 00:00:00 12:44 13:01 00:17 09.08.2020 12:44:00 09.08.2020 13:01:00 OBENAT1D0137 12:44
6 106991 mma 09.08.2020 00:00:00 13:03 13:07 00:04 09.08.2020 13:03:00 09.08.2020 13:07:00 OBENAT1D0137 12:44
7 102306 mma 09.08.2020 00:00:00 13:07 13:56 00:49 09.08.2020 13:07:00 09.08.2020 13:56:00 OBENAT1D0137 12:44
8 430386 mma 09.08.2020 00:00:00 13:56 14:06 00:10 09.08.2020 13:56:00 09.08.2020 14:06:00 OBENAT1D0137 12:44
9 117264 mma 09.08.2020 00:00:00 14:06 14:17 00:10 09.08.2020 14:06:00 09.08.2020 14:17:00 OBENAT1D0137 12:44
10 434302 mma 09.08.2020 00:00:00 14:17 14:41 00:23 09.08.2020 14:17:00 09.08.2020 14:41:00 OBENAT1D0137 12:44
11 333234 mma 09.08.2020 00:00:00 14:41 14:55 00:13 09.08.2020 14:41:00 09.08.2020 14:55:00 OBENAT1D0137 12:44
12 271379 mg 09.03.2020 00:00:00 10:24 10:25 00:00 09.03.2020 10:24:00 09.03.2020 10:25:00 OBENAT1D0117 10:24
13 269650 mg 09.03.2020 00:00:00 10:25 10:47 00:21 09.03.2020 10:25:00 09.03.2020 10:47:00 OBENAT1D0117 10:24
14 290765 mg 09.03.2020 00:00:00 12:19 12:19 00:00 09.03.2020 12:19:00 09.03.2020 12:19:00 OBENAT1D0117 12:19
15 280892 mg 09.03.2020 00:00:00 12:19 12:22 00:03 09.03.2020 12:19:00 09.03.2020 12:22:00 OBENAT1D0117 12:19
with my current query they just take the time from the row before. any help would be great
EDIT : I added 4 rows to the table to explain the problem more in detail. For example in the last 4 rows the client and worker are the same, but the connections should be grouped in 2 different groups. not in one. as it can be seen by the column "right_time".
One option to group the rows would be to use recursion. However, recursion can be slow on large data sets...
Sample data
I omitted some columns from your sample data and only used the columns I need and added an id
column for the initial values. If the id
column is not part of your data set, then you will have to compare both conn_start
and conn_end
to sort of find the next row for each combination of worker
and client
(because there can be rows with an equal conn_start
value like rows 14
and 15
).
create table data
(
id int,
worker nvarchar(3),
client nvarchar(15),
conn_start datetime2(0),
conn_end datetime2(0)
);
insert into data (id, worker, client, conn_start, conn_end) values
(5 , 'mma', 'OBENAT1D0137', '09.08.2020 12:44:00', '09.08.2020 13:01:00'),
(6 , 'mma', 'OBENAT1D0137', '09.08.2020 13:03:00', '09.08.2020 13:07:00'),
(7 , 'mma', 'OBENAT1D0137', '09.08.2020 13:07:00', '09.08.2020 13:56:00'),
(8 , 'mma', 'OBENAT1D0137', '09.08.2020 13:56:00', '09.08.2020 14:06:00'),
(9 , 'mma', 'OBENAT1D0137', '09.08.2020 14:06:00', '09.08.2020 14:17:00'),
(10, 'mma', 'OBENAT1D0137', '09.08.2020 14:17:00', '09.08.2020 14:41:00'),
(11, 'mma', 'OBENAT1D0137', '09.08.2020 14:41:00', '09.08.2020 14:55:00'),
(12, 'mg', 'OBENAT1D0117', '09.03.2020 10:24:00', '09.03.2020 10:25:00'),
(13, 'mg', 'OBENAT1D0117', '09.03.2020 10:25:00', '09.03.2020 10:47:00'),
(14, 'mg', 'OBENAT1D0117', '09.03.2020 12:19:00', '09.03.2020 12:19:00'),
(15, 'mg', 'OBENAT1D0117', '09.03.2020 12:19:00', '09.03.2020 12:22:00');
Solution
If this looks daunting, then make sure to check out this fiddle for a step-by-step construction.
with cte as
(
select d.id,
d.worker,
d.client,
d.conn_start,
d.conn_end,
datediff(minute,
coalesce(lag(d.conn_end) over(partition by d.worker, d.client order by d.id), d.conn_start),
d.conn_start) as diff_minutes
from data d
),
rcte as
(
select c.id,
c.worker,
c.client,
c.conn_start,
c.conn_end,
c.diff_minutes,
c.conn_start as conn_start_group
from cte c
where not exists ( select 'x'
from data d2
where d2.worker = c.worker
and d2.client = c.client
and d2.id < c.id )
union all
-- select next row for each (worker, client), keep conn_start_group if difference < 5 min
select c.id,
c.worker,
c.client,
c.conn_start,
c.conn_end,
c.diff_minutes,
case
when c.diff_minutes <= 5
then r.conn_start_group
else c.conn_start
end
from rcte r
join cte c
on c.worker = r.worker
and c.client = r.client
and c.id > r.id
and not exists ( select 'x'
from cte c2
where c2.worker = c.worker
and c2.client = c.client
and c2.id > r.id
and c2.id < c.id )
)
select rc.id,
rc.worker,
rc.client,
rc.conn_start,
rc.conn_end,
rc.conn_start_group
from rcte rc
order by rc.id;
Result
id worker client conn_start conn_end conn_start_group
-- ------ ------------ ------------------- ------------------- -------------------
5 mma OBENAT1D0137 2020-09-08 12:44:00 2020-09-08 13:01:00 2020-09-08 12:44:00
6 mma OBENAT1D0137 2020-09-08 13:03:00 2020-09-08 13:07:00 2020-09-08 12:44:00
7 mma OBENAT1D0137 2020-09-08 13:07:00 2020-09-08 13:56:00 2020-09-08 12:44:00
8 mma OBENAT1D0137 2020-09-08 13:56:00 2020-09-08 14:06:00 2020-09-08 12:44:00
9 mma OBENAT1D0137 2020-09-08 14:06:00 2020-09-08 14:17:00 2020-09-08 12:44:00
10 mma OBENAT1D0137 2020-09-08 14:17:00 2020-09-08 14:41:00 2020-09-08 12:44:00
11 mma OBENAT1D0137 2020-09-08 14:41:00 2020-09-08 14:55:00 2020-09-08 12:44:00
12 mg OBENAT1D0117 2020-09-03 10:24:00 2020-09-03 10:25:00 2020-09-03 10:24:00
13 mg OBENAT1D0117 2020-09-03 10:25:00 2020-09-03 10:47:00 2020-09-03 10:24:00
14 mg OBENAT1D0117 2020-09-03 12:19:00 2020-09-03 12:19:00 2020-09-03 12:19:00
15 mg OBENAT1D0117 2020-09-03 12:19:00 2020-09-03 12:22:00 2020-09-03 12:19:00
This should work. I used the following table so you may need to adjust the code to get it to work with your actual table. The column [ConnSetupCalc] was used to test the calculation rather than updating the actual data during testing and then having to re-create the correct data.
CREATE TABLE [dbo].[conn_data](
[SessionNo] [int] NULL,
[worker] [nvarchar](3) NULL,
[client] [nvarchar](15) NULL,
[ConnectionSetup] [datetime2](0) NULL,
[ConnectionEnd] [datetime2](0) NULL,
[RightTime] [nvarchar](15) NULL,
[ConnSetupCalc] [datetime] NULL
)
This Stored Proc should calculate the data in line with your example:
CREATE PROCEDURE UpdConn
AS
declare @MyCursor CURSOR;
declare @SessionNo int;
declare @Worker nvarchar(3);
declare @Client nvarchar(15);
declare @ConnStart datetime;
declare @ConnEnd datetime;
declare @Worker_prev nvarchar(3);
declare @Client_prev nvarchar(15);
declare @ConnStart_prev datetime;
declare @ConnEnd_prev datetime;
BEGIN
SET @MyCursor = CURSOR FOR
SELECT SessionNo
,worker
,client
,ConnectionSetup
,ConnectionEnd
FROM [dbo].[conn_data]
order by worker, client, ConnectionSetup
OPEN @MyCursor
FETCH NEXT FROM @MyCursor
INTO @SessionNo, @Worker, @Client, @ConnStart, @ConnEnd
WHILE @@FETCH_STATUS = 0
BEGIN
IF @Worker = @Worker_prev and @Client = @Client_prev and DATEDIFF(mi,@ConnEnd_prev,@ConnStart) between 0 and 5
BEGIN
UPDATE conn_data set ConnectionSetup = @ConnStart_prev where SessionNo = @SessionNo;
-- Test logic: UPDATE conn_data set ConnSetupCalc = @ConnStart_prev where SessionNo = @SessionNo;
END
ELSE
BEGIN
set @ConnStart_prev = @ConnStart;
END
SET @Worker_prev = @Worker;
SET @Client_prev = @Client;
SET @ConnEnd_prev = @ConnEnd;
FETCH NEXT FROM @MyCursor
INTO @SessionNo, @Worker, @Client, @ConnStart, @ConnEnd
END;
CLOSE @MyCursor ;
DEALLOCATE @MyCursor;
END;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.