Newsgroup: it.comp.appl.access
Titolo: Problema con date/ore su query db

Mi servirebbe un consiglio su una query usata per trovare la quantita' 
disponibile di carburante in un deposito, in un certo momento temporale
 
SCARICO - Ogni giorno vengono a far rifornimento i clienti, ogni 
rifornimento c'e' una registrazione di scarico con data, ora, quantita 
scaricata
 
CARICO - Circa una volta a settimana arriva il camion per caricare il 
deposito, per ogni carico c'e' una registrazione con data, ora, quantita 
caricata
 
RESIDUO - Periodicamente si fa un 'inventario' per misurare la quantita' 
di carburante nei depositi, per ogni inventario c'e' una registrazione 
con data, ora, quantita misurata
 
Bene, in qualsiasi momento la quantita' disponibile in deposito e' :
+ residuo (quantita' registrata su ultimo inventario)
+ acquistato (somma delle quantita' caricate dopo ultimo inventario)
- venduto (somma delle quantita' scaricate dopo ultimo inventario)
 
Esempio, in data 01/05/2017 ore 10:30.00 l'inventario misura 100 LT
Fino alla data 20/05/2017 ore 10.00.00 sono stati acquistati 1200 LT
Fino alla data 20/05/2017 ore 10.00.00 sono stati venduti 1000 LT
 
La 'quantita disponibile' in deposito, in data 20/05/2017 ore 10.00.00 
e'  100+1200-1000=300 LT
 
Bene, come fare per ottenere la 'quantita disponibile' in un qualunque 
momento?
 
quantita_disponibile_al(data/ora desiderata)
 
Da ricordare che oggi siamo il 25/05/2017 e quindi in archivio ci 
possono essere carichi/scarichi/inventari anche successivi alla 
'data/ora desiderata'
Ad esempio, oggi che siamo il 25/05/2017, potrei richiamare la funzione 
con quantita_disponibile_al("15/05/2017 14.00.00")
 
Mi e' chiaro che devo partire dall'inventario immediatamente precedente 
alla data/ora richiesta
Quello che non e' chiaro e' come fare per includere tutti i carichi e 
scarichi compresi tra data/ora inventario precedente e data/ora passata 
come parametro alla funzione
 
Voglio dire che non posso fare una:
 
select sum(LITRI) from CARICHI where DATA >= #01/05/2017# and ORA >= 
'00:00:00' and DATA <= #15/05/2017# and ORA <= '14:00:00'
 
perche' ovviamente le AND, messe cosi', trancerebbero troppe 
registrazioni che andrebbero incluse
E allura?
C'e' modo con una sciabolata di sql di arrivare all'obiettivo?
Come trasformare date/ore in un valore numerico in modo da poterle 
confrontare/sommare/sottrarre correttamente all'interno di una richiesta 
sql?


 
le movimentazioni sono registrate su un unica tabella?
 
 
 
 
---
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus
 
 

 le movimentazioni sono registrate su un unica tabella?
 
No su tre tabelle distinte, CARICHI, SCARICHI, CHIUSURE


Per il momento ho risolto cosi, ma se ci fosse soluzione migliore ben venga
In sostanza la query seleziona le righe che hanno:
 
1 Data_Registrazione > Data_Chiusura_precedente  or
2 Date uguali ma Ora_Registrazione > Ora_chiusura_precedente or
3 Date/Ora uguali ma Minuti_registrazione > Minuti_Chiusura_Precedente or
4 Date/Ora/minuti uguali ma Secondi_Registrazione > 
Secondi_Chiusura_Precedenti
 
and
 
5 Data_Registrazione < Data_Richiesta  or
6 Date uguali ma Ora_Registrazione < Ora_Richiesta or
7 Date/Ora uguali ma Minuti_registrazione < Minuti_Richiesta or
8 Date/Ora/minuti uguali ma Secondi_Registrazione <= Secondi_Richiesta
 
 
'--------------------------------------------------------------------------
' Rilevamento Scarichi dalla DATA / ORA RICHIESTA alla DATA / ORA ultima 
' chisura presente
'--------------------------------------------------------------------------
Selezione_SQL = "                  ( (DATA_REGISTRAZIONE > #" & 
dataSQL(DATA_CHIUSURA_PRECEDENTE) & "#) "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(DATA_CHIUSURA_PRECEDENTE) & "# and hour(ORA_REGISTRAZIONE) > " & 
Format$(ora_chiusura_precedente, "hh") & ") "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(DATA_CHIUSURA_PRECEDENTE) & "# and hour(ORA_REGISTRAZIONE) = " & 
Format$(ora_chiusura_precedente, "hh") & " and minute(ORA_REGISTRAZIONE) 
 > " & Format$(ora_chiusura_precedente, "nn") & ") "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(DATA_CHIUSURA_PRECEDENTE) & "# and hour(ORA_REGISTRAZIONE) = " & 
Format$(ora_chiusura_precedente, "hh") & " and minute(ORA_REGISTRAZIONE) 
= " & Format$(ora_chiusura_precedente, "nn") & " and 
second(ORA_REGISTRAZIONE) > " & Format$(ora_chiusura_precedente, "ss") & 
")) "
 
Selezione_SQL = Selezione_SQL & " and "
 
Selezione_SQL = Selezione_SQL & "  ( (DATA_REGISTRAZIONE < #" & 
dataSQL(data_richiesta) & "#) "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(data_richiesta) & "# and hour(ORA_REGISTRAZIONE) < " & 
Format$(ora_richiesta, "hh") & ") "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(data_richiesta) & "# and hour(ORA_REGISTRAZIONE) = " & 
Format$(ora_richiesta, "hh") & " and minute(ORA_REGISTRAZIONE) < " & 
Format$(ora_richiesta, "nn") & ") "
 
Selezione_SQL = Selezione_SQL & " or (DATA_REGISTRAZIONE = #" & 
dataSQL(data_richiesta) & "# and hour(ORA_REGISTRAZIONE) = " & 
Format$(ora_richiesta, "hh") & " and minute(ORA_REGISTRAZIONE) = " & 
Format$(ora_richiesta, "nn") & " and second(ORA_REGISTRAZIONE) <= " & 
Format$(ora_richiesta, "ss") & ")) "
 
Set MySNAPScarichi = CurrentDb.OpenRecordset("select sum(LITRI) as 
TOT_LITRI, sum(LITRI_A_15) as TOT_LITRI_A_15, sum(KG) as TOT_KG from 
SCARICOCARBURANTI where " & Selezione_SQL)

 In sostanza la query seleziona le righe che hanno:
[...]
 
È difficile non prevedere possa esistere un sistema meno
complicato per ottenere il saldo corrente dei movimenti.
Ma senza le tre tabelle mi è difficile determinarlo.
Puoi metterle online?
 
Bruno


"E' difficile NON prevedere possa esistere un sistema MENO complicato.."
L'ho riletta tre volte cercando di capirne il senso
Spero voglia dire "E' un sistema complicato per ottenere..."
Attendo comunque conferma
 
Per quanto riguarda le tabelle ridotte all'osso puoi considerare:
 
TABELLA CARICHI
	data_registrazione
	ora_registrazione
	litri
 
TABELLA SCARICHI
	data_registrazione
	ora_registrazione
	litri
 
TABELLA CHIUSURE
	data_registrazione
	ora_registrazione
	litri
 
 
La funzione che desidero realizzare e' finalizzata all'ottenimento della 
'giacenza' prodotto in un certo momento, e quindi del tipo
 
litri_in_data_ora_richiesta=quantita_disponibile_al(data_richiesta as 
string, ora_richiesta as string)
 
dove per 'giacenza' si intende la somma dei litri su 
CHIUSURE+CARICHI-SCARICHI
 
tenendo presente che la coppia data_richiesta/ora_richiesta puo' essere 
qualsiasi e quindi in archivio carichi/scarichi/chiusure potrebbero 
esserci registrazioni anche successive (in ordine temporale) a quella 
data_richiesta/ora_richiesta passati alla funzione
L'esempio della query al mio post precedente prevedeva, all'interno 
della funzione, l'individuazione del valore LITRI, DATA_REGISTRAZIONE, 
ORA_REGISTRAZIONE nella tabella CHIUSURE per 
data_registrazione/ora_registrazione immediatamente precedente alla 
data_richiesta/ora_richiesta passati alla funzione
Una volta trovati i litri di partenza, li sommo ai litri compresi nel 
periodo tra data_richiesta/ora_richiesta e 
data_registrazione/ora_registrazione come letti dalle tabelle CARICHI e 
SCARICHI
Spero di essermi capito
 
 
 
 
 
 
 
 
 

 	litri
Già, questo l'avevo capito, ma avevo chiesto le tabelle coi dati,
per non dovermele creare e caricare con alcuni record.
Senza le quali io non so risolvere il problema, né ho
intenzione di crearle e compilarle.
 
Spiacente
Bruno

PARTO DA QUI e provo a dire la mia ...

NON ho guardato la serie delle query che hai inserito in precedenza
e inizio da qui, per aggiungere un suggerimento (sperando si riveli tale...)
 
SE DAVVERO la CHIUSURA ha il valore "di compattazione quantità" alla data-ora indicata (registrata) io farei così:
 
Aggiungerei in una tabella temporanea (o in una query union) TUTTE le righe con i campi necessari al calcolo  delle tre tabelle, righe comprese fra la date richieste (ULTIMA CHIUSURA più vicina -ricavata a ritroso-, E movimenti di CARICO e SCARICO) AGGIUNGENDO UN CAMPO INDICATORE (ind) del tipo di "movimento" (es: 1: chiusura, 2: carico, 3: scarico).
 
A quel punto la sommatoria (SUM diretta ? SOMMATORIA in raggruppamento per prodotto = carburante inserito SOLO per comodità ?, TUTTE le righe sono di carburante ...) di -1*(Qtalitri * (ind=1)) -1*(Qtalitri * (ind=2)) +(Qtalitri * (ind=3)) dovrebbe dare il risultato richiesto


Anche avendo una tabella il problema non si risolve tanto facilmente
Il problema sta nel selezionare le righe con DATA/ORA da un certo 
momento X ad un certo momento Y
Ammesso di avere la tabella con 1000 righe, con movimenti dal 01/01/2016 
al 31/12/2016  ed io volessi conoscere la giacenza al 30/06/2016 ore 
15:00:00, come fai?
Non puoi semplicemente fare "select * from TABELLA where DATA <= 
'30/06/2016' and ORA <= '15:00:00'
Per questo chiedevo se c'e' modo di confrontare date/ore correttamente 
all'interno di una query sql
 


porterei il valore data + ora IN UN UNICO CAMPO CALCOLATO, con le adeguate conversioni che conosci meglio di me (non la prendere male: è così per davvero ...): forse cdbl(data) + cdbl(ora) ? 
e questo diventa un valore filtrabile (riconducendo il criterio "doppio" di selezione a questo unico valore numerico).
Poi "fa il suo gioco" il campo indicatore che, di fatto, determina se il valore nella riga è da sommare o sottrarre.
 
PS: questo modo di effettuare i calcoli delle giacenze di prodotti è per me un antico retaggio dell'utilizzo del foglio elettronico LOTUS 123 su DOS, da me adoperato come utente "avanzato" in aziende tessili dove appunto era da ottenere il risultato quantitativo di vari movimenti di filati (movimenti distinti appunto dall'indicatore: ce ne erano più di 12 ...)


 AGGIUNTA:
e forse non sono stato chiaro in precedenza,
la selezione delle righe deve avere come "INIZIO" la riga con il movimento di CHIUSURA APPENA PRECEDENTE al valore minore dell'intervallo date (prendendola),
e la selezione SI DEVE FERMARE alla riga uguale al valore maggiore dell'intervallo date con prendendo, in questo intervallo TUTTE le righe (che, così facendo, sono di carico e scarico)
Tutte queste righe devono poi avere il campo (aggiunto) indicatore del tipo movimento, da qui il fatto che venga fuori una tabella temporanea o una query union 
 
o forse sbaglio davvero tutto (porta pazienza ...)

 intenzione di crearle e compilarle.
 
Ripensandoci... queste le tre query
===================================
SELECT "Chiusure" AS A, Last(Tabella_Chiusure.Litri) AS LastOfLitri
FROM Tabella_Chiusure
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Chiusure";
 
SELECT "Carichi" AS A, Sum(Tabella_Carichi.Litri) AS SumOfLitri
FROM Tabella_Carichi
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Carichi";
 
SELECT "Scarichi" AS A, Sum(-[Litri]) AS SumOfLitri
FROM Tabella_Scarichi
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Scarichi";
 
Questa la UNION Query che le raggruppa
======================================
SELECT "Carichi" AS A, Sum(Tabella_Carichi.Litri) AS SumOfLitri
FROM Tabella_Carichi
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Carichi";
UNION
SELECT "Scarichi" AS A, Sum(-[Litri]) AS SumOfLitri
FROM Tabella_Scarichi
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Scarichi";
UNION SELECT "Chiusure" AS A, Last(Tabella_Chiusure.Litri) AS 
LastOfLitri
FROM Tabella_Chiusure
WHERE ((([Data_Registrazione]+[Ora_Registrazione])<=#3/30/2017 
19:0:0#))
GROUP BY "Chiusure";
 
Un lavoraccio, perché occorre comunque passare tre volte
i parametri Data e Ora iniziali negli opportuni formati
accettati dalle query.
 
Questa una una funzione VBA alla quale occorre passare
una sola volta i parametri Data e Ora come stringhe
nel formato locale, es: "30/3/17" e "19:15:12"
 
========================================
Public Function Giacenze(DataIni As String, OraIni As String)
Dim SQL As String, RS As Recordset, S
 
SQL = "SELECT Last(Tabella_Chiusure.Litri) AS LastOfLitri FROM 
Tabella_Chiusure "
SQL = SQL & "WHERE ((([Data_Registrazione]+[Ora_Registrazione])"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "#));"
Set RS = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = CDec(RS![LastOfLitri])
 
SQL = "SELECT Sum(Tabella_Carichi.Litri) AS SumOfLitri FROM 
Tabella_Carichi "
SQL = SQL & "WHERE ((([Data_Registrazione]+[Ora_Registrazione])"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "#));"
Set RS = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = CDec(S + RS![SumOfLitri])
 
SQL = "SELECT Sum(Tabella_Scarichi.Litri) AS SumOfLitri FROM 
Tabella_Scarichi "
SQL = SQL & "WHERE ((([Data_Registrazione]+[Ora_Registrazione])"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "#));"
Set RS = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = CDec(S - RS![SumOfLitri])
 
Giacenze = S
 
End Function
===========================
 
Bruno

 ===================================
 
Tutto sbagliato, come non detto
 
Bruno


Questa dovrebbe essere a posto
==============================
Public Function Giacenze(DataIni As String, OraIni As String)
Dim SQL As String, RS As Recordset, RS1 As Recordset, RS2 As Recordset, 
S
 
SQL = "SELECT Last(Tabella_Chiusure.Litri) AS LastOfLitri, "
SQL = SQL & "Last([Data_Registrazione]+[Ora_Registrazione]) AS DataFin 
"
SQL = SQL & " FROM Tabella_Chiusure WHERE 
((([Data_Registrazione]+[Ora_Registrazione])"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "#));"
Set RS = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = CDec(RS![LastOfLitri])
 
SQL = "SELECT Sum(Tabella_Carichi.Litri) AS SumOfLitri FROM 
Tabella_Carichi "
SQL = SQL & "WHERE [Data_Registrazione]+[Ora_Registrazione]"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "# And "
SQL = SQL & "[Data_Registrazione]+[Ora_Registrazione]># "
SQL = SQL & Format(RS![DataFin], "mm/dd/yyyy") & " " & 
Format(RS![DataFin], "hh:nn:ss") & "#;"
Set RS1 = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = S + CDec(RS1![SumOfLitri])
 
SQL = "SELECT Sum(Tabella_SCarichi.Litri) AS SumOfLitri FROM 
Tabella_Scarichi "
SQL = SQL & "WHERE [Data_Registrazione]+[Ora_Registrazione]"
SQL = SQL & "<=#" & Format(DataIni, "mm/dd/yyyy") & " " & 
Format(OraIni, "hh:nn:ss") & "# And "
SQL = SQL & "[Data_Registrazione]+[Ora_Registrazione]># "
SQL = SQL & Format(RS![DataFin], "mm/dd/yyyy") & " " & 
Format(RS![DataFin], "hh:nn:ss") & "#;"
Set RS2 = CurrentDb.OpenRecordset(SQL, dbOpenDynaset)
S = S - CDec(RS2![SumOfLitri])
 
Giacenze = S
 
End Function
============================
 
Bruno