Algoritmo SQL per la maggior parte degli eventi sovrapposti

3

Il problema

Sto cercando una query per aiutarmi a risolvere quanto segue:

  • Ho una serie di eventi
  • Ogni evento ha una data di inizio e di fine.
  • Molti di questi eventi si sovrappongono
  • La risposta che sto cercando è il numero massimo di eventi che si sovrappongono

Esempio

Dire che ho 5 eventi:

  • 1 gennaio - > 9 gennaio
  • 7 gennaio - > 12 gennaio
  • 8 gennaio - > 10 gennaio
  • 10 gennaio - > 15 gennaio
  • 12 gennaio - > 17 gen

3 di questi eventi si sovrappongono al 9 gennaio, che è il massimo degli eventi sovrapposti, quindi la risposta è 3.

(Ci sono anche 3 eventi che si sovrappongono il 10 gennaio, ma è la stessa risposta)

Quello che ho provato

Se lo stavo facendo in memoria, potrei fare questo:

  • Per ogni evento:
    • Ottieni la data di inizio
    • Conta le date che includono questo evento
  • Scegli l'evento con il conteggio più alto.

Ma ci sono 2 problemi con questo:

  • Non sembra molto efficiente
  • Non è molto SQL-y (cioè è procedurale piuttosto che basato su set)

Domanda

Come posso implementare qualcosa di simile in SQL?

Note

  • Non mi interessa trovare le date di inizio / fine degli eventi più sovrapposti. Ho solo bisogno di un conteggio
  • Non mi interessa quanto spesso accade il massimo, ho solo bisogno del massimo. Quindi, nell'esempio sopra, so che ci sono due occasioni in cui 3 eventi si sovrappongono, ma ho solo bisogno del "3".
  • Se l'evento A termina lo stesso giorno dell'inizio dell'evento B, viene considerato come sovrapposto
posta Kramii 06.03.2018 - 12:51
fonte

2 risposte

2

Potrebbe essere più performante scrivere questo codice, non sql.

Nel codice, vorrei ordinare gli articoli in base alla data di inizio, quindi alla data di fine. Camminale e controlla se si sovrappone al prossimo oggetto. Se lo fa, incrementa il suo contatore di sovrapposizione e ripeti: controlla la voce successiva si sovrappone al tuo oggetto. In caso contrario, passa alla successiva.

In SQL, puoi farlo con un self join per elencare tutte le sovrapposizioni.

Questo mostrerà tutte le sovrapposizioni:

select a.eventid from events a
inner join events b 
on a.end > b.start and a.start < b.end

Puoi quindi raggrupparli per eventid, selezionare il conteggio e prendere l'evento con il conteggio massimo.

select top 1 eventid, count(*) as c
from 
    (select a.eventid from events a
    inner join events b 
    on a.end > b.start and a.start < b.end)
group by eventid
order by c desc
    
risposta data 06.03.2018 - 14:08
fonte
0

Un'altra strategia nei database relazionali consiste nell'avere una tabella con un record per ogni giorno di calendario. Questo aiuta nella situazione in cui stai cercando di determinare i giorni che non esistono nel tuo sistema. È semplicemente più facile per loro lavorare con i dati che ci sono invece di affidarsi al database per creare dati per calcolo.

Con quella tabella e la tua tabella di eventi, potresti unirti a loro e fare una semplice aggregazione (SQL Server):

create table Datelist (
HistoryDate datetime not null
)
insert into DateList (HistoryDate)
values 
( '1/1/2018')   
, ('1/2/2018')
...

create table event (
StartDate datetime not null
, EndDate datetime not null
)

insert into event (StartDate, EndDate)
values ('01/01/2018', '01/09/2018')
, ('01/07/2018', '01/12/2018')
, ('01/08/2018', '01/10/2018')
, ('01/10/2018', '01/15/2018')
, ('01/12/2018', '01/17/2018')

select max(c.EventCount) as maxEvents
from (
select d.HistoryDate
    , count(d.HistoryDate) as EventCount
from DateList as d
inner join event as e
on d.HistoryDate between e.StartDate and e.EndDate
group by d.HistoryDate
) as c

La query non è troppo difficile da leggere, ma devi capire il contenuto della tabella "DateList" precompilata. È possibile eseguire la sottoquery per visualizzare l'elenco effettivo di ciascuna data a scopo di test.

    
risposta data 07.03.2018 - 16:48
fonte

Leggi altre domande sui tag