Así es como se ven las posibles superposiciones, donde 'A' es el intervalo de "referencia". Tenga en cuenta que la consulta a continuación (muy, muy abajo) no da el mismo resultado que ninguna de las respuestas publicadas hasta ahora.
-- A |------|
-- B |-|
-- C |---|
-- D |---|
-- E |---|
-- F |---|
-- G |---|
-- H |---|
-- I |---|
"B" no se superpone a "A" en absoluto. "C" linda con él. {"D", "E", "F", "G"} lo superpone. "H" linda con él. "I" no se superpone en absoluto.
create table calls_nov (
sid varchar(5) primary key,
starttime timestamp not null,
endtime timestamp not null
);
insert into calls_nov values
('A', '2012-01-04 08:00:00', '2012-01-04 08:00:10'),
('B', '2012-01-04 07:50:00', '2012-01-04 07:50:03'),
('C', '2012-01-04 07:59:57', '2012-01-04 08:00:00'),
('D', '2012-01-04 07:59:57', '2012-01-04 08:00:03'),
('E', '2012-01-04 08:00:01', '2012-01-04 08:00:04'),
('F', '2012-01-04 08:00:07', '2012-01-04 08:00:10'),
('G', '2012-01-04 08:00:07', '2012-01-04 08:00:13'),
('H', '2012-01-04 08:00:10', '2012-01-04 08:00:13'),
('I', '2012-01-04 08:00:15', '2012-01-04 08:00:18');
Puede ver todos los intervalos superpuestos de esta manera. (Acabo de usar to_char() para facilitar la visualización de todos los datos. Puede omitirlo en producción).
select t1.sid, to_char(t1.starttime, 'HH12:MI:SS'),
to_char(t1.endtime, 'HH12:MI:SS'),
t2.sid, to_char(t2.starttime, 'HH12:MI:SS'),
to_char(t2.endtime, 'HH12:MI:SS')
from calls_nov t1
inner join calls_nov t2 on (t2.starttime, t2.endtime)
overlaps (t1.starttime, t1.endtime)
order by t1.sid, t2.sid;
A 08:00:00 08:00:10 A 08:00:00 08:00:10
A 08:00:00 08:00:10 D 07:59:57 08:00:03
A 08:00:00 08:00:10 E 08:00:01 08:00:04
A 08:00:00 08:00:10 F 08:00:07 08:00:10
A 08:00:00 08:00:10 G 08:00:07 08:00:13
B 07:50:00 07:50:03 B 07:50:00 07:50:03
C 07:59:57 08:00:00 C 07:59:57 08:00:00
C 07:59:57 08:00:00 D 07:59:57 08:00:03
D 07:59:57 08:00:03 A 08:00:00 08:00:10
D 07:59:57 08:00:03 C 07:59:57 08:00:00
D 07:59:57 08:00:03 D 07:59:57 08:00:03
D 07:59:57 08:00:03 E 08:00:01 08:00:04
E 08:00:01 08:00:04 A 08:00:00 08:00:10
E 08:00:01 08:00:04 D 07:59:57 08:00:03
E 08:00:01 08:00:04 E 08:00:01 08:00:04
F 08:00:07 08:00:10 A 08:00:00 08:00:10
F 08:00:07 08:00:10 F 08:00:07 08:00:10
F 08:00:07 08:00:10 G 08:00:07 08:00:13
G 08:00:07 08:00:13 A 08:00:00 08:00:10
G 08:00:07 08:00:13 F 08:00:07 08:00:10
G 08:00:07 08:00:13 G 08:00:07 08:00:13
G 08:00:07 08:00:13 H 08:00:10 08:00:13
H 08:00:10 08:00:13 G 08:00:07 08:00:13
H 08:00:10 08:00:13 H 08:00:10 08:00:13
I 08:00:15 08:00:18 I 08:00:15 08:00:18
Puede ver en esta tabla que "A" debe contar 5, incluyéndose a sí mismo. "B" debe contar 1; se superpone a sí mismo, pero ningún otro intervalo lo superpone. Eso parece lo correcto.
Contar es sencillo, pero corre como una tortuga rota. Esto se debe a que evaluar una superposición requiere mucho trabajo.
select t1.sid, count(t2.sid) as num_concurrent
from calls_nov t1
inner join calls_nov t2 on (t2.starttime, t2.endtime)
overlaps (t1.starttime, t1.endtime)
group by t1.sid
order by num_concurrent desc;
A 5
D 4
G 4
E 3
F 3
H 2
C 2
I 1
B 1
Para obtener un mejor rendimiento, puede usar la "tabla" anterior en una expresión de tabla común y contar en función de eso .
with interval_table as (
select t1.sid as sid_1, t1.starttime, t1.endtime,
t2.sid as sid_2, t2.starttime, t2.endtime
from calls_nov t1
inner join calls_nov t2 on (t2.starttime, t2.endtime)
overlaps (t1.starttime, t1.endtime)
order by t1.sid, t2.sid
)
select sid_1, count(sid_2) as num_concurrent
from interval_table
group by sid_1
order by num_concurrent desc;