我在数据时间类型中拥有数据库中的sesions日期(会话的开始和结束)。我需要计算在具体时间和每个用户类型中完成的并发会话数。这意味着我需要计算每个用户和每天的同时会话数。
数据库使用SQL Server,表格如下:
SESSION GRU_ID SES_INI SES_END
233550 Enfermeros 2016-02-10 07:49:32.000 2016-02-10 14:51:46.000
233551 Enfermeros 2016-02-10 07:57:05.000 2016-02-10 12:37:03.000
233552 Enfermeros 2016-02-10 08:03:09.000 2016-02-10 14:44:30.000
233553 Enfermeros 2016-02-10 08:04:49.000 2016-02-10 13:22:58.000
233556 Enfermeros 2016-02-10 08:06:52.000 2016-02-10 14:54:29.000
233559 Enfermeros 2016-02-10 08:08:00.000 2016-02-10 10:49:38.000
233560 Enfermeros 2016-02-10 08:08:09.000 2016-02-10 14:25:19.000
233564 Enfermeros 2016-02-10 08:13:54.000 2016-02-10 14:51:19.000
233565 Enfermeros 2016-02-10 08:14:35.000 2016-02-10 11:46:16.000
233567 Enfermeros 2016-02-10 08:16:01.000 2016-02-10 15:05:20.000
233568 Enfermeros 2016-02-10 08:17:01.000 2016-02-10 12:40:05.000
233569 Enfermeros 2016-02-10 08:19:13.000 2016-02-10 14:46:54.000
233570 Enfermeros 2016-02-10 08:17:50.000 2016-02-10 14:48:10.000
233579 Enfermeros 2016-02-10 08:29:52.000 2016-02-10 14:21:38.000
233580 Enfermeros 2016-02-10 08:31:11.000 2016-02-10 10:09:36.000
233584 Enfermeros 2016-02-10 08:38:52.000 2016-02-10 13:22:06.000
233585 Enfermeros 2016-02-10 08:40:11.000 2016-02-10 11:08:10.000
233589 Enfermeros 2016-02-10 08:48:09.000 2016-02-11 16:59:06.000
233603 Enfermeros 2016-02-10 09:24:56.000 2016-02-10 09:37:29.000
233607 Enfermeros 2016-02-10 09:29:31.000 2016-02-10 16:00:31.000
233623 Enfermeros 2016-02-10 10:08:34.000 2016-02-10 12:16:28.000
233624 Enfermeros 2016-02-10 10:09:36.000 2016-02-10 10:10:27.000
233625 Enfermeros 2016-02-10 10:10:51.000 2016-02-10 10:46:30.000
选择我正在使用的是下一个。问题是这个选择总结了在ses_ini和ses_end之间的这段时间内发生的会话,但它并不意味着同时发生会话。
SELECT GRU_ID AS TIPO_USUARIO, count(GRU_ID) AS TOTAL
FROM
dbo.USUARIOS INNER JOIN
dbo.SESIONES ON dbo.USUARIOS.CODIGOUSUARIO = dbo.SESIONES.CODIGOUSUARIO INNER JOIN
dbo.GRUPOS ON dbo.USUARIOS.CODIGOGRUPO = dbo.GRUPOS.CODIGOGRUPO
WHERE
SES_FECHAFIN BETWEEN @SES_INI AND @SES_END AND
DAY(ses_fechainicio) = 10 AND MONTH(ses_INI)= 2 AND YEAR(ses_END) = 2016 AND ses_duracion IS NOT NULL
GROUP BY GRU_ID
我需要某种算法来计算这些数据的所有同步会话。
编辑:
如果我有这样的话:
Session A: 9.00 - 10.00
Session B: 9.00 - 9.30
Session C: 9.30 - 9.45
Session D: 9.40 - 10:00
在第一场A会议之间,有下一个同步会议:A-B和A-C-D(会议B和C我不同时考虑) 通过我所做的选择,我得到了9.00-10.00之间的所有会话,即4,但我真的需要获得最多的同步会话,即3,我需要为每个会话执行相同的操作。
我做的完整脚本是这样的:
一个循环(同时)多年,一个循环几个月,另一个循环(嵌套循环)。然后一个光标选择一天的所有会话(使用循环)。一旦我每天获得所有会话,我进行插入(使用选择我粘贴)填充一个包含5列的表:Simultanious会话,GRU_ID(用户类型:医生,管理员,护士等)日,月和年。问题在于插入,因为我只能得到每个会话之间的会话总数,而不是同时会话。对不起,如果我解释不好,但很难,我的英语不是很好......
答案 0 :(得分:1)
这个想法是将所有时间放在一个大的列表中,其中+1
用于会话开始,-1
用于会话结束。然后累积总和非常接近你想要的。
所以:
select gru_id, dt,
sum(val) over (partition by gru_id order by dt) as concurrent_sessions
from ((select gru_id, ses_ini as dt, 1 as val from t
) union all
(select gru_id, ses_end, -1 as val from t
)
) g;
这给出了数据中每次的数字。你可能想以某种方式总结它。你现有的问题在这一点上并不清楚 - 如果你想指定一个特定的输出,你应该问另一个问题。
这是处理关系意义上的“接近”。如果用户在完全相同的时间启动和停止会话,则可能存在“一个一个”的错误,具体取决于您希望如何计算会话。
答案 1 :(得分:0)
这样的事情......计算在另一个会话期间开始或结束的会话数。然后按日期和最大数量进行汇总。
SELECT
[GRU_ID]
,CAST([Ses_Ini] AS DATE) AS [Date]
,MAX([Sessions Count]) AS [Max Connections]
FROM (
SELECT
[Data].[Session]
,[Data].[GRU_ID]
,[Data].[Ses_Ini]
,[Data].[Ses_End]
,COUNT(DISTINCT [D2].[Session]) AS [Sessions Count]
FROM [Data]
INNER JOIN [Data] AS [D2]
ON ([d2].[Ses_Ini] BETWEEN [Data].[Ses_Ini] AND [Data].[Ses_End])
OR ([d2].[Ses_End] BETWEEN [Data].[Ses_Ini] AND [Data].[Ses_End])
GROUP BY
[Data].[Session]
,[Data].[GRU_ID]
,[Data].[Ses_Ini]
,[Data].[Ses_End]
) AS [SessionCounts]
GROUP BY
[GRU_ID]
,CAST([Ses_Ini] AS DATE)
答案 2 :(得分:0)
如果新会话的ses_ini
位于另一个会话的ses_ini
和ses_end
之间,那么会话就是并发的。
这是实施:
create table #sess([session] int,gru_id varchar(20),ses_ini datetime,ses_end datetime)
insert #sess
values
(233550, 'Enfermeros', '2016-02-10 07:49:32.000', '2016-02-10 14:51:46.000'),
(233551 ,'Enfermeros', '2016-02-10 07:57:05.000', '2016-02-10 12:37:03.000'),
(233552 ,'Enfermeros', '2016-02-10 08:03:09.000', '2016-02-10 14:44:30.000'),
(233553 ,'Enfermeros', '2016-02-10 08:04:49.000', '2016-02-10 13:22:58.000'),
(233556 ,'Enfermeros', '2016-02-10 08:06:52.000', '2016-02-10 14:54:29.000'),
(233559 ,'Enfermeros', '2016-02-10 08:08:00.000', '2016-02-10 10:49:38.000'),
(233560 ,'Enfermeros', '2016-02-10 08:08:09.000', '2016-02-10 14:25:19.000'),
(233564 ,'Enfermeros', '2016-02-10 08:13:54.000', '2016-02-10 14:51:19.000'),
(233565 ,'Enfermeros', '2016-02-10 08:14:35.000', '2016-02-10 11:46:16.000'),
(233567 ,'Enfermeros', '2016-02-10 08:16:01.000', '2016-02-10 15:05:20.000'),
(233568 ,'Enfermeros', '2016-02-10 08:17:01.000', '2016-02-10 12:40:05.000'),
(233569 ,'Enfermeros', '2016-02-10 08:19:13.000', '2016-02-10 14:46:54.000'),
(233570 ,'Enfermeros', '2016-02-10 08:17:50.000', '2016-02-10 14:48:10.000'),
(233579 ,'Enfermeros', '2016-02-10 08:29:52.000', '2016-02-10 14:21:38.000'),
(233580 ,'Enfermeros', '2016-02-10 08:31:11.000', '2016-02-10 10:09:36.000'),
(233584 ,'Enfermeros', '2016-02-10 08:38:52.000', '2016-02-10 13:22:06.000'),
(233585 ,'Enfermeros', '2016-02-10 08:40:11.000', '2016-02-10 11:08:10.000'),
(233589 ,'Enfermeros', '2016-02-10 08:48:09.000', '2016-02-11 16:59:06.000'),
(233603 ,'Enfermeros', '2016-02-10 09:24:56.000', '2016-02-10 09:37:29.000'),
(233607 ,'Enfermeros', '2016-02-10 09:29:31.000', '2016-02-10 16:00:31.000'),
(233623 ,'Enfermeros', '2016-02-10 10:08:34.000', '2016-02-10 12:16:28.000'),
(233624 ,'Enfermeros', '2016-02-10 10:09:36.000', '2016-02-10 10:10:27.000'),
(233625 ,'Enfermeros', '2016-02-10 10:10:51.000', '2016-02-10 10:46:30.000')
--select all concurrent sessions
select s.session,s1.session s1_sess,s.ses_ini,s.ses_end,s1.ses_ini s1_ini
from #sess s
inner join #sess s1 on s1.ses_ini >= s.ses_ini and s1.ses_ini < s.ses_end and s.session<>s1.session
order by 1
-- calculate the number of concurrent sessions
;with ss as (
select s.session,s1.session s1_sess,s.ses_ini,s.ses_end,s1.ses_ini s1_ini
from #sess s
inner join #sess s1 on s1.ses_ini >= s.ses_ini and s1.ses_ini < s.ses_end and s.session<>s1.session
)
select session, count(s1_sess) cnt
from ss
group by session
order by 2 desc
我希望这就是你要找的东西。
更新+添加:
declare @dtStart datetime, @dtEnd datetime
select @dtStart= convert(varchar(13),(select min(ses_ini) from #sess), 120)+':00:00'
,@dtEnd= convert(varchar(13),dateadd(hh,1,(select max(ses_end) from #sess)), 120)+':00:00'
;with tm as (
select 1 num, @dtStart sesStart, dateadd(hh,1,@dtStart) sesEnd
union all
select num+1,dateadd(hh,1,sesStart),dateadd(hh,1,sesEnd)
from tm where tm.sesStart<@dtEnd
)
select 'sess '+cast(num as varchar) sess,sesStart,sesEnd, count(session) cnt
from tm
inner join #sess s on (s.ses_ini>=tm.sesStart and s.ses_ini < tm.sesEnd) or
(s.ses_end>tm.sesStart and s.ses_end <= tm.sesEnd)
group by num,sesStart,sesEnd
结果:
sess sesStart sesEnd cnt
sess 1 2016-02-10 07:00:00.000 2016-02-10 08:00:00.000 2
sess 2 2016-02-10 08:00:00.000 2016-02-10 09:00:00.000 16
sess 3 2016-02-10 09:00:00.000 2016-02-10 10:00:00.000 2
sess 4 2016-02-10 10:00:00.000 2016-02-10 11:00:00.000 5
sess 5 2016-02-10 11:00:00.000 2016-02-10 12:00:00.000 2
sess 6 2016-02-10 12:00:00.000 2016-02-10 13:00:00.000 3
sess 7 2016-02-10 13:00:00.000 2016-02-10 14:00:00.000 2
sess 8 2016-02-10 14:00:00.000 2016-02-10 15:00:00.000 8
sess 9 2016-02-10 15:00:00.000 2016-02-10 16:00:00.000 1
sess 10 2016-02-10 16:00:00.000 2016-02-10 17:00:00.000 1
sess 34 2016-02-11 16:00:00.000 2016-02-11 17:00:00.000 1
更新2:每个时间间隔内存在的会话
declare @dtStart datetime, @dtEnd datetime
select @dtStart= convert(varchar(13),(select min(ses_ini) from #sess), 120)+':00:00'
,@dtEnd= convert(varchar(13),dateadd(hh,1,(select max(ses_end) from #sess)), 120)+':00:00'
;with tm as (
select 1 num, @dtStart sesStart, dateadd(hh,1,@dtStart) sesEnd
union all
select num+1,dateadd(hh,1,sesStart),dateadd(hh,1,sesEnd)
from tm where tm.sesStart<@dtEnd
)
select 'sess '+cast(num as varchar) sess,sesStart,sesEnd, count(session) cnt
from tm
inner join #sess s on (s.ses_end > tm.sesStart and s.ses_ini <= tm.sesEnd)
group by num,sesStart,sesEnd
结果:
sess sesStart sesEnd cnt
sess 1 2016-02-10 07:00:00 2016-02-10 08:00:00 2
sess 2 2016-02-10 08:00:00 2016-02-10 09:00:00 18
sess 3 2016-02-10 09:00:00 2016-02-10 10:00:00 20
sess 4 2016-02-10 10:00:00 2016-02-10 11:00:00 22
sess 5 2016-02-10 11:00:00 2016-02-10 12:00:00 18
sess 6 2016-02-10 12:00:00 2016-02-10 13:00:00 16
sess 7 2016-02-10 13:00:00 2016-02-10 14:00:00 13
sess 8 2016-02-10 14:00:00 2016-02-10 15:00:00 11
sess 9 2016-02-10 15:00:00 2016-02-10 16:00:00 3
sess 10 2016-02-10 16:00:00 2016-02-10 17:00:00 2
sess 11 2016-02-10 17:00:00 2016-02-10 18:00:00 1
sess 12 2016-02-10 18:00:00 2016-02-10 19:00:00 1
sess 13 2016-02-10 19:00:00 2016-02-10 20:00:00 1
sess 14 2016-02-10 20:00:00 2016-02-10 21:00:00 1
sess 15 2016-02-10 21:00:00 2016-02-10 22:00:00 1
sess 16 2016-02-10 22:00:00 2016-02-10 23:00:00 1
sess 17 2016-02-10 23:00:00 2016-02-11 00:00:00 1
sess 18 2016-02-11 00:00:00 2016-02-11 01:00:00 1
sess 19 2016-02-11 01:00:00 2016-02-11 02:00:00 1
sess 20 2016-02-11 02:00:00 2016-02-11 03:00:00 1
sess 21 2016-02-11 03:00:00 2016-02-11 04:00:00 1
sess 22 2016-02-11 04:00:00 2016-02-11 05:00:00 1
sess 23 2016-02-11 05:00:00 2016-02-11 06:00:00 1
sess 24 2016-02-11 06:00:00 2016-02-11 07:00:00 1
sess 25 2016-02-11 07:00:00 2016-02-11 08:00:00 1
sess 26 2016-02-11 08:00:00 2016-02-11 09:00:00 1
sess 27 2016-02-11 09:00:00 2016-02-11 10:00:00 1
sess 28 2016-02-11 10:00:00 2016-02-11 11:00:00 1
sess 29 2016-02-11 11:00:00 2016-02-11 12:00:00 1
sess 30 2016-02-11 12:00:00 2016-02-11 13:00:00 1
sess 31 2016-02-11 13:00:00 2016-02-11 14:00:00 1
sess 32 2016-02-11 14:00:00 2016-02-11 15:00:00 1
sess 33 2016-02-11 15:00:00 2016-02-11 16:00:00 1
sess 34 2016-02-11 16:00:00 2016-02-11 17:00:00 1