Ho una tabella in un database Oracle. Lo schema èjoin (self) a intervalli di tempo
create table PERIODS
(
ID NUMBER,
STARTTIME TIMESTAMP,
ENDTIME TIMESTAMP,
TYPE VARCHAR2(100)
)
ho due differenti TYPE's
: TYPEA
e TYPEB
. Hanno tempi di inizio e di fine indipendenti e possono sovrapporsi. Quello che vorrei trovare sono i periodi di TYPEB
avviati, completamente contenuti o terminati entro un determinato periodo di TYPEA
.
Ecco quello che mi è venuto in mente finora (con alcuni dati di esempio)
WITH mydata
AS (SELECT 100 ID,
To_timestamp('2015-08-01 11:00', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 11:20', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEA' TYPE
FROM dual
UNION ALL
SELECT 110 ID,
To_timestamp('2015-08-01 11:30', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 11:50', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEA' TYPE
FROM dual
UNION ALL
SELECT 120 ID,
To_timestamp('2015-08-01 12:00', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 12:20', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEA' TYPE
FROM dual
UNION ALL
SELECT 105 ID,
To_timestamp('2015-08-01 10:55', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 11:05', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEB' TYPE
FROM dual
UNION ALL
SELECT 108 ID,
To_timestamp('2015-08-01 11:05', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 11:15', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEB' TYPE
FROM dual
UNION ALL
SELECT 111 ID,
To_timestamp('2015-08-01 11:15', 'YYYY-MM-DD HH24:MI') STARTTIME,
To_timestamp('2015-08-01 12:25', 'YYYY-MM-DD HH24:MI') ENDTIME,
'TYPEB' TYPE
FROM dual),
typeas
AS (SELECT starttime,
endtime
FROM mydata
WHERE TYPE = 'TYPEA'),
typebs
AS (SELECT id,
starttime,
endtime
FROM mydata
WHERE TYPE = 'TYPEB')
SELECT id
FROM typebs b
join typeas a
ON (b.starttime BETWEEN a.starttime AND a.endtime)
OR (b.starttime BETWEEN a.starttime AND a.endtime
AND b.endtime BETWEEN a.starttime AND a.endtime)
OR (b.endtime BETWEEN a.starttime AND a.endtime)
ORDER BY id;
Questo sembra funzionare in linea di principio, il risultato della query di cui sopra è
ID
----------
105
108
111
quindi seleziona i tre periodi TYPEB
avviati o terminati all'interno del primo periodo TYPEA
.
Il problema è che la tabella ha circa 200.000 voci e già a questa dimensione la query precedente è piuttosto lenta --- il che è molto sorprendente per me dato che il numero di entrambe le voci TYPEA
e TYPEB
è piuttosto basso (1-2k)
Esiste un modo più efficiente per eseguire questo tipo di self join? Ho perso qualcos'altro nella mia domanda?
La tabella ha 200.000 righe, ci sono solo due diversi valori di 'tipo', ma ogni' tipo' ha solo 1.000-2.000 righe. Questo implica che ~ 196.000 righe nella tabella abbiano un 'NULL' per il loro' type'? Se stai chiedendo una domanda di ottimizzazione, puoi pubblicare il piano di query che stai ricevendo e quali indici sono disponibili? –
La tabella ha 200k righe, la maggior parte delle quali ha un tipo che non è rilevante per me per questa query. – Erik
@JustinCave potrebbe essere una domanda di ottimizzazione, ma forse sono semplicemente ignaro di qualche altra caratteristica che renderebbe questa query molto più veloce senza messa a punto. – Erik