Hi,
I have a task that is meant to summarize several connections coming in to a given set of ports (trunks), into timeslots and count the results. The thing is that I would like to achieve two type of counts:
- One count should count the total number of connection to a
Trunk
in the given slot (30 minutes per slot) - Secondly I would like to find out the MAX number of connection that occurred simultaneously: such as there have been 10 connections totally however only 3 of them was connected on simultaneously
Table: RAW_DATA
GatewayName StartDateTime DisconnectDateTime ConnectionDuration Trunk
GW1 2021-02-24 20:01:00.0000000 2021-02-24 20:05:30.0000000 270000 T1 -- 1 *
GW1 2021-02-24 20:05:20.6000000 2021-02-24 20:07:50.1000000 149500 T1 -- 2 *
GW1 2021-02-24 20:04:50.0000000 2021-02-24 20:08:24.0000000 214000 T1 -- 3 *
GW1 2021-02-24 20:15:50.0000000 2021-02-24 20:17:00.0000000 70000 T1 -- 0
GW1 2021-02-24 20:20:50.0000000 2021-02-24 20:21:00.0000000 10000 T1 -- 1
GW1 2021-02-24 20:20:59.0000000 2021-02-24 20:24:00.0000000 181000 T1 -- 2
GW1 2021-02-24 20:25:00.0000000 2021-02-24 20:28:30.0000000 210000 T1 -- 0
GW2 2021-02-24 20:41:49.0000000 2021-02-24 20:43:24.0000000 95000 T2
GW3 2021-02-24 22:46:54.2000000 2021-02-24 22:48:25.2000000 91000 T1
GW99 2021-02-24 22:47:25.1000000 2021-02-24 22:47:54.4000000 29300 T2
The source data table is depicted above, I added some comments on the first few lines indicating how I would count. So as you can see the first three lines occur simultaneously (at leas parts of it) then on the forth line I start over (indicated with a 0 here). So what I would like is to save the three indicated with *
to be the "winner" giving a count Simultaneous = 3
I tried to add it into a store procedure, I have been able to get the tally table and counting the 'ALL' , however I'm clueless when it comes to counting the Simultaneous
connections.
CREATE OR ALTER PROCEDURE [schemma].[TrunkSummery]
@date datetime2(7),
@period int
AS
BEGIN
-- Creat timeslotable
with numbers(val) as
(select 1 union all select val + 1 from numbers where val < 48) -- 48 hence 30 * 2 = 60 min -> 24h
select @date, nbr.val,
dateadd(minute, (nbr.val - 1) * 30, @date) as period_start,
dateadd(minute, (nbr.val ) * 30, @date) as period_end
from numbers as nbr
order by nbr.val;
-- Enummurate over timeslot table and RAW_DAtA
with numbers(val) as
(select 1 union all select val + 1 from numbers where val < 48), -- 48 hence 30 * 2 = 60 min -> 24h
periods as (
select @date as [date], nbr.val,
dateadd(minute, (nbr.val - 1) * 30, @date) as period_start,
dateadd(minute, (nbr.val ) * 30, @date) as period_end
from numbers as nbr)
select pers.period_start, @period as Period, src.trunk, count(src.trunk) as 'all'
/*, count(Simultaneous) as 'sim' */
--from periods as pers left join @raw_data as src
from periods as pers inner join @raw_data as src
on src.StartDateTime >= pers.period_start and src.StartDateTime < pers.period_end
group by src.trunk, pers.period_start, pers.period_end
order by src.trunk;
END
GO
EXECUTE [schemma].[TrunkSummery] @date = '20210224', @period = 30;
GO
Output tables
-- Current
period_start Period trunk all
2021-02-24 20:00:00.0000000 30 T1 7
2021-02-24 22:30:00.0000000 30 T1 1
2021-02-24 20:30:00.0000000 30 T2 1
2021-02-24 22:30:00.0000000 30 T2 1
-- Desiered
period_start Period trunk all sim
2021-02-24 20:00:00.0000000 30 T1 7 3
2021-02-24 22:30:00.0000000 30 T1 1 1
2021-02-24 20:30:00.0000000 30 T2 1 1
2021-02-24 22:30:00.0000000 30 T2 1 1
Is this possible somehow?
Thanks to everyone in advance :)
update 1
After thinking reading up a bit more, maybe I could use a ‘LEAD’ function somehow to see if ‘disconnectDateTime’ on current row is less then ‘StartDateTime’ on the row below it an store the number of hops until ‘DisconnectDateTime’ is less than ‘StartDateTime’. And continue on like this for all rows within the slot. And if a clause surpass the last MAX count update it with the new record.
Update 2
I have added a temp table that is run before I run the timeslot sorting, the purpus of this table is to look at the next rows StartDateTime
to see if it is before current rows DisconnectDateTime
GatewayName StartDateTime DisconnectDateTime ConDur Trunk nrDDT sim
GW1 2021-02-24 20:01:00.0 2021-02-24 20:05:30.0 270000 T1 2021-02-24 20:04:50.0 2 -- OK
GW1 2021-02-24 20:04:50.0 2021-02-24 20:08:24.0 214000 T1 2021-02-24 20:05:20.6 2 -- Bad: 3
GW1 2021-02-24 20:05:20.6 2021-02-24 20:07:50.1 149500 T1 2021-02-24 20:15:50.0 0
GW1 2021-02-24 20:15:50.0 2021-02-24 20:17:00.0 70000 T1 2021-02-24 20:20:50.0 0
GW1 2021-02-24 20:20:50.0 2021-02-24 20:21:00.0 10000 T1 2021-02-24 20:20:59.0 2 -- OK
GW1 2021-02-24 20:20:59.0 2021-02-24 20:24:00.0 181000 T1 2021-02-24 20:25:00.0 0
GW1 2021-02-24 20:25:00.0 2021-02-24 20:28:30.0 210000 T1 2021-02-24 22:46:54.2 0
GW3 2021-02-24 22:46:54.2 2021-02-24 22:48:25.2 91000 T1 NULL 0
GW2 2021-02-24 20:41:49.0 2021-02-24 20:43:24.0 95000 T2 2021-02-24 22:47:25.1 0
GW99 2021-02-24 22:47:25.1 2021-02-24 22:47:54.4 29300 T2 NULL 0
The issue is that I would like to increase a count if my case
is met (sim column), I have tried with both a global and a local variable however it is resetting for every row and I can't force it back to 0
if my else
clause is entered.
CREATE OR ALTER PROCEDURE GenerateTrunkSum
@date datetime2(7),
@period int
AS
BEGIN
DECLARE @raw_data table
(
GatewayName varchar(23),
StartDateTime datetime2(7),
DisconnectDateTime datetime2(7),
ConnectionDuration int ,
Trunk varchar(10)
);
INSERT INTO @raw_data values('GW1', '2021-02-24 20:01:00.0', '2021-02-24 20:05:30.0', DATEDIFF(millisecond, '2021-02-24 20:01:00.0', '2021-02-24 20:05:30.0'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:05:20.6', '2021-02-24 20:07:50.1', DATEDIFF(millisecond, '2021-02-24 20:05:20.6', '2021-02-24 20:07:50.1'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:04:50.0', '2021-02-24 20:08:24.0', DATEDIFF(millisecond, '2021-02-24 20:04:50.0', '2021-02-24 20:08:24.0'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:15:50.0', '2021-02-24 20:17:00.0', DATEDIFF(millisecond, '2021-02-24 20:15:50.0', '2021-02-24 20:17:00.0'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:20:50.0', '2021-02-24 20:21:00.0', DATEDIFF(millisecond, '2021-02-24 20:20:50.0', '2021-02-24 20:21:00.0'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:20:59.0', '2021-02-24 20:24:00.0', DATEDIFF(millisecond, '2021-02-24 20:20:59.0', '2021-02-24 20:24:00.0'), 'T1')
INSERT INTO @raw_data values('GW1', '2021-02-24 20:25:00.0', '2021-02-24 20:28:30.0', DATEDIFF(millisecond, '2021-02-24 20:25:00.0', '2021-02-24 20:28:30.0'), 'T1')
INSERT INTO @raw_data values('GW2', '2021-02-24 20:41:49.0 ', '2021-02-24 20:43:24.0', DATEDIFF(millisecond, '2021-02-24 20:41:49.0 ', '2021-02-24 20:43:24.0'), 'T2')
INSERT INTO @raw_data values('GW3', '2021-02-24 22:46:54.2', '2021-02-24 22:48:25.2', DATEDIFF(millisecond, '2021-02-24 22:46:54.2', '2021-02-24 22:48:25.2'), 'T1')
INSERT INTO @raw_data values('GW99', '2021-02-24 22:47:25.1', '2021-02-24 22:47:54.4', DATEDIFF(millisecond, '2021-02-24 22:47:25.1', '2021-02-24 22:47:54.4'), 'T2')
declare @localvar int -- Alt 2
set @localvar = 1
SELECT GatewayName, StartDateTime, DisconnectDateTime, ConnectionDuration, Trunk, LEAD(StartDateTime, 1, NULL) OVER ( PARTITION BY Trunk ORDER BY StartDateTime ) as nrDDT,
CASE
WHEN DATEDIFF(MILLISECOND, LEAD(StartDateTime, 1, NULL) OVER ( PARTITION BY Trunk ORDER BY StartDateTime ), DisconnectDateTime) >= 0 THEN @localvar + 1 -- Add if Match 1 = 1 M3 = 3 etc
ELSE 0 -- Reset @localvar = 0
END AS sim
INTO #Temp
FROM @raw_data;
select * from #Temp;
-- Creat timeslotable
with numbers(val) as
(select 1 union all select val + 1 from numbers where val < 48)
select @date, nbr.val,
dateadd(minute, (nbr.val - 1) * 30, @date) as period_start,
dateadd(minute, (nbr.val ) * 30, @date) as period_end
from numbers as nbr
order by nbr.val;
--Enummerate
with numbers(val) as
(select 1 union all select val + 1 from numbers where val < 48),
periods as (
select @date as [date], nbr.val,
dateadd(minute, (nbr.val - 1) * 30, @date) as period_start,
dateadd(minute, (nbr.val ) * 30, @date) as period_end
from numbers as nbr)
select pers.period_start, @period as Period, src.trunk, count(src.GatewayName) as 'all',
-- Case Added in update 2
CASE
WHEN MAX(src.sim) < 1 THEN 1 -- if max is 0 set 1, defaults to at least one active
ELSE MAX(src.sim)
END AS simultaneous
--from periods as pers left join HDO.CDR_RAW as src
from periods as pers inner join #Temp as src
on src.StartDateTime >= pers.period_start and src.StartDateTime < pers.period_end
group by src.trunk, pers.period_start
order by src.trunk
END
GO
EXECUTE GenerateTrunkSum @date = '20210224', @period = 1800;
So my question is: Does someone know how-to get this count mechanic to work ? The reason for why I want it like this is to be able to do a MAX
within my last select statement (see CASE
)
Update 3
Once I checked the current answer below by @bbaird, with a larger more true dataset; StartDateTime
& DisconnectDateTime
could overflow into a different period.
Current output
period_start period_end Period Trunk All Sim
2021-02-24 20:00:00.0 2021-02-24 20:30:00.0 30 E1 2 4
2021-02-24 20:30:00.0 2021-02-24 21:00:00.0 30 E1 23 6
2021-02-24 20:30:00.0 2021-02-24 21:00:00.0 30 E2 1 1
2021-02-24 20:00:00.0 2021-02-24 20:30:00.0 30 T1 2 4
2021-02-24 20:30:00.0 2021-02-24 21:00:00.0 30 T1 23 6
2021-02-24 20:30:00.0 2021-02-24 21:00:00.0 30 T2 1 1
As you can see the period 2021-02-24 20:00:00.0
for Trunk = 'E1'
has a total count of 2 but a Sim of 4. I can't figure out why this is.
If we look at the rows surrounding 2021-02-24 20:00:00.0
for E1
-- @raw_data
1 ('GW1', '2021-02-24 20:23:43.1', '2021-02-24 20:32:32.9', ..., 'T1', 'E1' ),
2 ('GW1', '2021-02-24 20:24:34.6', '2021-02-24 20:33:05.1', ..., 'T1', 'E1' ),
3 ('GW1', '2021-02-24 20:31:09.5', '2021-02-24 20:32:51.4', ..., 'T1', 'E1' ),
4 ('GW1', '2021-02-24 20:32:42.3', '2021-02-24 20:33:09.3', ..., 'T1', 'E1' ),
5 ('GW1', '2021-02-24 20:34:50.6', '2021-02-24 20:37:30.9', ..., 'T1', 'E1' ),
6 ('GW1', '2021-02-24 20:35:34.2', '2021-02-24 20:36:25.4', ..., 'T1', 'E1' ),
Looking at the data, I would say that the row 1 and 2 should be the only one that are counted(count(*) as 'ALL')
for sim T:20:00
as et seems based on the output shown above however, I'm not sure where the extra two Sim
counts comes from. Based on some analyses I have done of the output, It could be Connectionsummary.ConnectionCount
from ,MAX(COALESCE(ConnectionSummary.ConnectionCount,0)) AS Sim
since ConnectionSummary
seams to have consecutive rows even after a 30 min mark is meet; I assume that this needs to be group into timeslots before enumerating it.
Secondly it becomes more trickery when it comes to 20:30
for a solid query I assume that row 1 and 2 should probably be counted as part of sim since row 3 occurs simultaneously. Is there any possibility to count entries twice if the surpasses a 30 min-mark(00/30) ?