微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查找最大同时出现次数,如果满足条件则增加变量 目前的结果更新 1

如何解决查找最大同时出现次数,如果满足条件则增加变量 目前的结果更新 1

我有一项任务旨在将进入一组给定端口(中继)的多个连接汇总到时隙中并计算结果。问题是我想实现两种类型的计数:

  • 一个计数应该计算给定槽中 Trunk 的连接总数(每个槽 30 分钟)
  • 其次,我想找出同时发生的最大连接数:例如总共有 10 个连接,但其中只有 3 个同时连接。表中注释表示“计数组”

表:RAW_DATA

GatewayName StartDateTime               disconnectDateTime      ConDur  Trunk
GW1         2021-02-24 20:01:00.0       2021-02-24 20:05:30.0   270000  T1  --1,nextRow.Start is before discon   
GW1         2021-02-24 20:04:50.0       2021-02-24 20:08:24.0   214000  T1  --2   
GW1         2021-02-24 20:05:20.6       2021-02-24 20:07:50.1   149500  T1  --3   
GW1         2021-02-24 20:15:50.0       2021-02-24 20:17:00.0   70000   T1  --0   
GW1         2021-02-24 20:20:50.0       2021-02-24 20:21:00.0   10000   T1  --1   
GW1         2021-02-24 20:20:59.0       2021-02-24 20:24:00.0   181000  T1  --2   
GW1         2021-02-24 20:23:59.0       2021-02-24 20:28:30.0   271000  T1  --3   
GW1         2021-02-24 20:26:00.0       2021-02-24 20:29:30.0   210000  T1  --4   
GW1         2021-02-24 20:27:00.0       2021-02-24 20:29:31.0   151000  T1  --5   
GW3         2021-02-24 22:46:54.2       2021-02-24 22:48:25.2   91000   T1  --0  
GW2         2021-02-24 20:41:49.0       2021-02-24 20:43:24.0   95000   T2  --0   
GW99        2021-02-24 22:47:25.1       2021-02-24 22:47:54.4   29300   T2  --0 

目前的结果

我正在运行一个存储过程,该过程创建了一个我用来生成时间段的计数表。

另外我创建了一个临时表,在我运行时间段排序之前运行,这个表的目的是查看下一行 StartDateTime 以查看它是否在当前行 disconnectDateTime 之前.此表是作为测试表构建的,以查看是否可以在遇到零 (0) 之前以某种方式对出现次数进行计数和分组,以便稍后执行 max 以一次性获得最多出现次数。不幸的是,我无法弄清楚这个机制。

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   1 -- count row below
GW1         2021-02-24 20:04:50.0       2021-02-24 20:08:24.0   214000  T1      2021-02-24 20:05:20.6   1 -- counted
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 -- counted
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 -- jump to else
GW1         2021-02-24 20:20:50.0       2021-02-24 20:21:00.0   10000   T1      2021-02-24 20:20:59.0   1
GW1         2021-02-24 20:20:59.0       2021-02-24 20:24:00.0   181000  T1      2021-02-24 20:23:59.0   1
GW1         2021-02-24 20:23:59.0       2021-02-24 20:28:30.0   271000  T1      2021-02-24 20:26:00.0   1
GW1         2021-02-24 20:26:00.0       2021-02-24 20:29:30.0   210000  T1      2021-02-24 20:27:00.0   1
GW1         2021-02-24 20:27:00.0       2021-02-24 20:29:31.0   151000  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

问题是,如果满足我的 case,我想增加计数(sim 列),我尝试使用全局变量和局部变量,但是它正在为每一行重置,我可以'如果输入了我的 0 子句,请不要强制返回 else

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)
);
-- Createing test data
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:05:30.0'),'T1')
INSERT INTO @raw_data values('GW1','2021-02-24 20:05:20.6','2021-02-24 20:07:50.1','2021-02-24 20:07:50.1'),'2021-02-24 20:04:50.0','2021-02-24 20:08:24.0','2021-02-24 20:08:24.0'),'2021-02-24 20:15:50.0','2021-02-24 20:17:00.0','2021-02-24 20:17:00.0'),'2021-02-24 20:20:50.0','2021-02-24 20:21:00.0','2021-02-24 20:21:00.0'),'2021-02-24 20:20:59.0','2021-02-24 20:24:00.0','2021-02-24 20:24:00.0'),'2021-02-24 20:25:00.0','2021-02-24 20:28:30.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','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','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','2021-02-24 22:47:54.4'),'T2')


-- Variable should be increased if not null 
declare @localvar int 
set @localvar = 0
-- Store value in max if 0 is meet and current @localvar is greater then @max
declare @max int 
set @max = 0

   SELECT GatewayName,StartDateTime,disconnectDateTime,ConnectionDuration,Trunk,LEAD(StartDateTime,1,NULL) OVER ( PARTITION BY Trunk ORDER BY  StartDateTime ) as nrDDT,CASE 
           WHEN DATEDIFF(MILLISECOND,NULL) OVER ( PARTITION BY Trunk ORDER BY  StartDateTime ),disconnectDateTime) >= 0 THEN @localvar + 1 -- Add if Match 1 = 1 M3 = 3 etc
           ELSE -- possible update @max and 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,(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],@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; 

所以我的问题是:有人知道如何让这个计数机制起作用吗?我之所以想要这样的原因是为了能够在我的最后一个选择语句中执行 MAX(请参阅 CASE

--- Current output
period_start            period  trunk all   simultaneous
2021-02-24 20:00:00.0   1800    T1    9     1
2021-02-24 22:30:00.0   1800    T1    1     1
2021-02-24 20:30:00.0   1800    T2    1     1
2021-02-24 22:30:00.0   1800    T2    1     1

--- What it should be based on input
period_start            period  trunk all   simultaneous
2021-02-24 20:00:00.0   1800    T1    9     5 -- See RAW_table for clarification
2021-02-24 22:30:00.0   1800    T1    1     1
2021-02-24 20:30:00.0   1800    T2    1     1
2021-02-24 22:30:00.0   1800    T2    1     1

示例输出

Trunk  Start                                Period   All  sim
T1       2021:02:24 22:30:0.0     1800      5     2

更新 1

看着 Sørens 的回答,我试着把它inner join 到我 30 分钟的时间。
像这样 设置无计数 使用 [dbo_CDR] 去

CREATE OR ALTER PROCEDURE [dbo].[GenerateTrunkSumv1]
@date datetime2(1),@ST datetime2(1),@DT datetime2(1),@tn varchar(23),@period int
AS
BEGIN

WITH TrunkGroup
AS (
    SELECT
        IngresstrunkGroup as Trunk,disconnectDateTime
    FROM 
        [dbo].[CDR_RAW]

    UNION ALL

    SELECT 
        EgresstrunkGroup,disconnectDateTime
    FROM 
        [dbo].[CDR_RAW]
),Times AS
(SELECT
        rd.StartDateTime tm,rd.Trunk
    FROM TrunkGroup rd
    UNION
    SELECT
        rd.disconnectDateTime,rd.Trunk
    FROM TrunkGroup rd),intervals
AS
(SELECT
        tm tm1,LEAD(tm,1) OVER (PARTITION BY Trunk ORDER BY tm) tm2,Trunk
    FROM Times)
SELECT
    i.Trunk,i.tm1,i.tm2,COUNT(*) simultaneous
INTO #TEMP
FROM intervals i
INNER JOIN TrunkGroup rd
    ON rd.disconnectDateTime >= i.tm1
        AND rd.StartDateTime < i.tm2
        AND i.Trunk = rd.Trunk
        AND i.tm2 IS NOT null
GROUP BY i.Trunk,i.tm2
ORDER BY i.Trunk,i.tm1

;

WITH Numbers(val) AS
(
SELECT
    1 
    
    UNION ALL
    
SELECT
    val + 1 
FROM
    numbers 
WHERE
    val < 48
)
SELECT
PeriodSummary.period_start,PeriodSummary.period_end,PeriodSummary.Period,PeriodSummary.Trunk,PeriodSummary.[all],PeriodSummary.simultaneous
FROM
(
    SELECT
    pers.period_start,pers.period_end,@period as [Period],src.Trunk,src.simultaneous,COUNT(*) as [all]
    FROM
    (
        SELECT
        dateadd(minute,(val - 1) * 30,'20210224') as period_start,(val    ) * 30,'20210224') as period_end 
        FROM
        numbers
    ) pers 
INNER JOIN
    #TEMP as src 
    ON  src.tm1 >= pers.period_start
            AND src.tm1 < pers.period_end
GROUP BY
    src.Trunk,pers.period_start,src.simultaneous
) PeriodSummary

END
GO

EXECUTE [dbo].[GenerateTrunkSumv1] @date = '20210224',@period = 1800,@ST = '2021-02-24 20:00:00.0',@DT = '2021-02-24 22:30:00.0000000',@tn = 'test';
SELECT @@ROWCOUNT as 'Inserted'
GO

解决方案的问题是,如果时间段超过 30 分钟标记,其中一个值(开始/断开连接时间),我会收到重复的线路

电流输出

period_start              period_end                Period  Trunk   all     simultaneous
2021-02-24 20:00:00.0     2021-02-24 20:30:00.0     1800    I1      1       1
2021-02-24 20:00:00.0     2021-02-24 20:30:00.0     1800    I1      1       2
2021-02-24 20:30:00.0     2021-02-24 21:00:00.0     1800    I1      6       1
2021-02-24 20:30:00.0     2021-02-24 21:00:00.0     1800    I1      22      2
2021-02-24 20:30:00.0     2021-02-24 21:00:00.0     1800    I1      16      3
2021-02-24 20:30:00.0     2021-02-24 21:00:00.0     1800    I2      1       1
2021-02-24 20:30:00.0     2021-02-24 21:00:00.0     1800    I2      2       2

如上所示,第一行出现了两次,因为它有一个通过标记的条目。

--Surrounding rows causing this issue
I1  2021-02-24 20:23:43.1   2021-02-24 20:24:34.6   1
I1  2021-02-24 20:24:34.6   2021-02-24 20:31:09.5   2
I1  2021-02-24 20:31:09.5   2021-02-24 20:32:32.9   3
I1  2021-02-24 20:32:32.9   2021-02-24 20:32:42.3   3
I1  2021-02-24 20:32:42.3   2021-02-24 20:32:51.4   3
I1  2021-02-24 20:32:51.4   2021-02-24 20:33:05.1   3

有没有人知道一种解决方案,可以摆脱必须每 30 分钟 (00:00 / 00:30) 开始的锁定时间段,而是从第一个时间段开始创建 30 分钟。

如果可以更改第二行以反映异常值的开始/断开时间,则可以选择。

解决方法

如果我要找到同时连接,我不会只看下一个条目。

考虑您有每个连接的开始和结束时间。使用这些时间进行所有连续间隔,您将拥有数据集的所有“有趣”间隔。 然后将这些间隔与您的原始数据连接起来,您可以计算每个间隔中有多少连接。既然你总是有事情发生,你一定会抓住一切。

首先我选择所有时间:

WITH Times
AS
(SELECT
        rd.StartDateTime tm,rd.Trunk
    FROM #raw_data rd
    UNION
    SELECT
        rd.DisconnectDateTime,rd.Trunk
    FROM #raw_data rd)
    

这只是您数据集的所有时间 - 按主干分组,因为我们希望将它们分开。

然后创建所有间隔:

intervals
AS
(SELECT
        tm tm1,LEAD(tm,1) OVER (PARTITION BY Trunk ORDER BY tm) tm2,Trunk
    FROM Times)

这里我们得到一天中的第一时间、一天中的第二时间、一天中的第二时间到一天中的第三时间等。也就是说,我们将所有连接的时间段划分为精确的时间间隔,以 a 开头或结尾连接开始或断开。

现在我们只需要加入原始数据,看看每个区间有多少连接:

SELECT
    i.Trunk,i.tm1,i.tm2,COUNT(*) simultaneous
FROM intervals i
INNER JOIN #raw_data rd
    ON rd.DisconnectDateTime >= i.tm1
        AND rd.StartDateTime < i.tm2
        AND i.Trunk = rd.Trunk
        AND i.tm2 IS NOT null
GROUP BY i.Trunk,i.tm2
ORDER BY i.trunk,i.tm1

这给出了这个表:

+-------+-----------------------------+-----------------------------+--------------+
| Trunk |             tm1             |             tm2             | simultaneous |
+-------+-----------------------------+-----------------------------+--------------+
| T1    | 2021-02-24 20:01:00.0000000 | 2021-02-24 20:04:50.0000000 |            1 |
| T1    | 2021-02-24 20:04:50.0000000 | 2021-02-24 20:05:20.6000000 |            2 |
| T1    | 2021-02-24 20:05:20.6000000 | 2021-02-24 20:05:30.0000000 |            3 |
| T1    | 2021-02-24 20:05:30.0000000 | 2021-02-24 20:07:50.1000000 |            3 |
| T1    | 2021-02-24 20:07:50.1000000 | 2021-02-24 20:08:24.0000000 |            2 |
| T1    | 2021-02-24 20:08:24.0000000 | 2021-02-24 20:15:50.0000000 |            1 |
| T1    | 2021-02-24 20:15:50.0000000 | 2021-02-24 20:17:00.0000000 |            1 |
| T1    | 2021-02-24 20:17:00.0000000 | 2021-02-24 20:20:50.0000000 |            1 |
| T1    | 2021-02-24 20:20:50.0000000 | 2021-02-24 20:20:59.0000000 |            1 |
| T1    | 2021-02-24 20:20:59.0000000 | 2021-02-24 20:21:00.0000000 |            2 |
| T1    | 2021-02-24 20:21:00.0000000 | 2021-02-24 20:24:00.0000000 |            2 |
| T1    | 2021-02-24 20:24:00.0000000 | 2021-02-24 20:25:00.0000000 |            1 |
| T1    | 2021-02-24 20:25:00.0000000 | 2021-02-24 20:28:30.0000000 |            1 |
| T1    | 2021-02-24 20:28:30.0000000 | 2021-02-24 22:46:54.2000000 |            1 |
| T1    | 2021-02-24 22:46:54.2000000 | 2021-02-24 22:48:25.2000000 |            1 |
| T2    | 2021-02-24 20:41:49.0000000 | 2021-02-24 20:43:24.0000000 |            1 |
| T2    | 2021-02-24 20:43:24.0000000 | 2021-02-24 22:47:25.1000000 |            1 |
| T2    | 2021-02-24 22:47:25.1000000 | 2021-02-24 22:47:54.4000000 |            1 |
+-------+-----------------------------+-----------------------------+--------------+

现在你可以根据你设定的时间段加入它,记住让时间间隔开放,你可以找到每个时间段内同时连接的最大数量。

完整查询在这里:

WITH Times
AS
(SELECT
        rd.StartDateTime tm,rd.Trunk
    FROM #raw_data rd),intervals
AS
(SELECT
        tm tm1,Trunk
    FROM Times)
SELECT
    i.Trunk,i.tm1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。