Newsgroup: it.comp.appl.access
Titolo: somma di tempi parzialmente sovrapposti: come fare?

Un database mi registra gli interventi dei tecnici in certe condizioni
di urgenza. 
Ogni intervento e' una riga della tabella in cui si registrano l'ora di
inizio e l'ora di fine e, tramite calcolo, la durata dell'intervento.
A volte un tecnico avvia l'intervento, lo conclude e resta in attesa di
un altro intervento. Se fosse sempre cosi', la semplice somma della
durata degli interventi, staccati fra loro, mi direbbe quanto tempo
effettivo ha lavorato il tecnico.
Altre volte pero' mentre il tecnico sta eseguendo il primo intervento,
arriva un'altra urgenza e si deve avviare un altro record, i cui tempi
si sovrappongono al precedente. Es. il primo evento inizia alle 8 e
finisce alle 9, il secondo inizia alle 8:30 e finisce alle 9:30. In
questo caso il tecnico ha lavorato per un'ora e mezza, mentre la somma
bruta dei due interventi fa 2 ore.
Io avrei bisogno, partendo dalla tabella che registra l'inizio e la fine
di tutti gli interventi giornalieri, di ottenere una tabella che mi dia
giorno per giorno la somma del tempo effettivamente lavorato dal
tecnico, al netto delle sovrapposizioni.
Avete un'idea di come risolvere? 
Grazie
P. Bianchi

 ha scritto nel messaggio
news:3BAA1EBB...@so.sorry.it...

Se la tabella che contiene i dati relativi ad ogni intervento si chiama
Tabella1 ed ha la seguente struttura:
ID                    Contatore e chiave primaria
Tecnico            Numerico (codice del tecnico)
DataI                Data/ora (data intervento)
Inizio                Data/ora (ora inizio intervento)
Fine                  Data/ora (ora fine intervento)
Come vedi non ho inserito scientemente un campo che contiene la durata
dell'intervento (Fine - Inizio): non ritengo opportuno memorizzare in una
tabella i campi calcolati, ti creerebbero complicazioni inutili; d'altra
parte, ogni volta che ti servirà, potrai sempre farlo con una query o in una
casella di testo non associata di una maschera o di un report.
Se ti servisse di calcolare la durata reale di ogni intervento (cioè al
netto delle sovrapposizioni) puoi usare una query che abbia il seguente
codice SQL:
SELECT Tabella1.ID, Tabella1.Tecnico, Tabella1.DataI, Tabella1.Inizio,
Tabella1.Fine, (IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24 AS OreIntervento
FROM Tabella1;
La durata reale di ogni intervento viene determinata nel campo calcolato
OreIntervento.
Se invece ti serve conoscere, giorno per giorno, le ore effettivamente
lavorate da ogni tecnico, usa una query di raggruppamento che ha il seguente
codice SQL:
SELECT Tabella1.DataI, Tabella1.Tecnico,
Sum(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24 AS OreGiornata
FROM Tabella1
GROUP BY Tabella1.DataI, Tabella1.Tecnico;
Il numero di ore effettivamente lavorate, giorno per giorno da ogni tecnico,
viene determinato nel campo calcolato OreGiornata.
Se infine, malgrado io te lo sconsigli caldamente, vuoi che i risultati
della query precedente vengano memorizzati in una tabella chiamata Tabella2,
usa una query di creazione tabella che ha il seguente codice SQL:
SELECT Tabella1.DataI, Tabella1.Tecnico,
Sum(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24 AS OreGiornata INTO Tabella2
FROM Tabella1
GROUP BY Tabella1.DataI, Tabella1.Tecnico;
Il numero di ore effettivamente lavorate, giorno per giorno da ogni tecnico,
viene memorizzato nel campo OreGiornata di Tabella2.
Il tipo dati dei campi che contengono i risultati, anziche Data/ora, è
numerico con lunghezza in doppia precisione; questo ti faciliterà la somma
di tali campi per ottenere risultati che superano 24 ore, inoltre ti
permetterà, senza complicazioni,  di moltiplicare tali risultati per un
costo orario, al fine di determinare il costo dell'/gli intervento/i; ne
consegue che i risultati sono espressi in ore e frazioni di ore e non in ore
e minuti, ovvero due ore e mezzo ti verranno restituite come 2,5 e non come
02:30 . Se comunque li volessi ottenere in ore e minuti (ma te lo
sconsiglio), è sufficiente non effettuare la moltiplicazione per 24 e
formattare i campi in Ora breve 24h.
--
Roberto
---------------------------------------------
il Sito Comune di it.comp.appl.access:
http://www.sitocomune.com
---------------------------------------------

 FROM Tabella1;
Mi accingo a sperimentare le tue proposte, ma fin da subito un GRAZIE
grosso cosi' per la tua estrema disponibilita'!
:-)
B.

 B.
Ho ricevuto un tuo messaggio al quale non ho risposto al tuo indirizzo
e-mail, ma ti rispondo solo nel NG: d'altra parte questa è una regola
fondamentale che da tempo ci siamo dati in questo NwesGroup.
Tu dici che oltre ad esserci interventi sovrapposti SOLO PARZIALMENTE, come
esplicitamente indicato nell'oggetto e nell'esempio del tuo messaggio, ne
esistono alcuni TOTALMENTE contenuti in un altro intervento (es.: primo
intervento dalle 9:00 alle 12:00, e altro intervento dalle 9:30 alle 10:30).
Dici inoltre che un intervento totalmente contenuto in un altro intervento
deve avere una durate reale uguale a zero.
Perché venga prevista anche questa eventualità, la prima query deve avere il
seguente codice SQL:
SELECT Tabella1.ID, Tabella1.Tecnico, Tabella1.DataI, Tabella1.Inizio,
Tabella1.Fine, IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Inizio] & "# And Fine>#" & [Fine] &
"#")),(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24,0) AS OreIntervento
FROM Tabella1;
la seconda query deve avere il seguente codice SQL:
SELECT Tabella1.DataI, Tabella1.Tecnico,
Sum(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Inizio] & "# And Fine>#" & [Fine] &
"#")),(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24,0)) AS OreGiornata
FROM Tabella1
GROUP BY Tabella1.DataI, Tabella1.Tecnico;
e la terza query deve avere il seguente codice SQL:
SELECT Tabella1.DataI, Tabella1.Tecnico,
Sum(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Inizio] & "# And Fine>#" & [Fine] &
"#")),(IIf(IsNull(DLookUp("ID","Tabella1","DataI =#" &
Format$([DataI],"mm/dd/yyyy") & "# And Tecnico=" & [Tecnico] & " And
Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")),[Fine],DLookUp("Inizio","Tabella1","ID=" &
DLookUp("ID","Tabella1","DataI =#" & Format$([DataI],"mm/dd/yyyy") & "# And
Tecnico=" & [Tecnico] & " And Inizio<#" & [Fine] & "# And Fine>#" & [Fine] &
"#")))-[Inizio])*24,0)) AS OreGiornata INTO Tabella2
FROM Tabella1
GROUP BY Tabella1.DataI, Tabella1.Tecnico;
Inoltre la data dell'intervento deve essere contenuta nel campo DataI, ed i
campi Inizio e Fine debbono contenere solo un orario e no anche la relativa
data (ovvero 9:30 e non 18/05/2001 9:30). Di fatto le query, così come sono
state architettate, prevedono che Inizio e Fine appartengano allo stesso
giorno.
Mi auguro che tu legga questo mio messaggio, ed in caso contrario per te il
messaggio che hai inviato al mio indirizzo e-mail resterà senza risposta.


 Mi auguro che tu legga questo mio messaggio, ed in caso contrario 
leggo, leggo ... anche se seguire i ng non sarebbe conforme al 100% alla
ns policy aziendale :-)
Ciao e grazie ancora.

 FROM Tabella1;
Non fuzniona ancora come mi aspetto
Prendiamo il caso del giorno 16/8/2000, e' sempre in servizio
l'operatore 1 
Le chiamate notturne sono conteggiate correttamente, in particolare la
terza prestazione e' entrocontenuta nella seconda e viene giustamente
valorizzata zero.
ID	Tecnico	DataI	Inizio	Fine	OreIntervento
7405	1	16/08/00	1:39:00	2:00:50		0.363888888888889
7406	1	16/08/00	2:14:00	2:58:33		0.7425
7407	1	16/08/00	2:22:00	2:36:03		0
7408	1	16/08/00	5:20:00	5:36:34		0.276111111111111
Quelle diurne non lo sono, in pratica il tizio ha iniziato alle 8:35
accettando via via un certo numero di urgenze, alle 11:11 ne ha chiuse
un certo numero,  poi e' rimasto in servizio a terminare due rogne che
ha concluso alle 14:30. 
Morale la somma di ore uomo deve valere dalle 8:35 alle 14:30 ossia
quasi 6 ore,  mentre qui ci sono troppe ore intermedie valorizzate. 
7409	1	16/08/00	8:35:00	11:11:36	1.18333333333333
7410	1	16/08/00	8:45:00	11:11:36	1.01666666666667
7411	1	16/08/00	8:46:00	11:11:36	1
7412	1	16/08/00	8:48:00	11:11:36	0.966666666666667
7413	1	16/08/00	9:11:00	11:11:36	0.583333333333334
7414	1	16/08/00	9:12:00	11:11:36	0.566666666666666
7415	1	16/08/00	9:13:00	11:11:36	0.549999999999999
7416	1	16/08/00	9:22:00	11:11:36	0.4
7417	1	16/08/00	9:45:00	11:11:36	1.66666666666666E-02
7418	1	16/08/00	9:46:00	14:30:29	4.74138888888889
7419	1	16/08/00	9:49:00	11:11:36	0
7420	1	16/08/00	9:50:00	11:11:36	0
7421	1	16/08/00	9:51:00	11:11:36	0
7422	1	16/08/00	9:53:00	11:11:36	0
7423	1	16/08/00	9:54:00	11:11:36	0
7424	1	16/08/00	9:55:00	11:36:01	0
7425	1	16/08/00	9:59:00	11:11:36	0
7426	1	16/08/00	10:02:00	11:27:02	0
7427	1	16/08/00	10:10:00	11:27:02	0
7428	1	16/08/00	13:32:00	14:30:29	0.974722222222224
Purtroppo la prestazione "lunga" che entrocontiene le altre non appare
in un particolare ordine e sebbene io non abbia sinceramente ancora ben
decodificato il tuo codice (perche' non sono familiare con dlookup) ho
il sospetto a pelle che piu' che operatori di maggiore e miniore (fra
consecutivi?) si debbano usare (se ci sono) funzioni del tipo massimo -
minimo entro determinati range di record.
Ciao!
B.

 B.
