Home Page
Articoli
Tips & Tricks
News
Forum
Archivio Forum
Blogs
Sondaggi
Rss
Video
Utenti
Chi Siamo
Contattaci
Username:
Password:
Login
Registrati ora!
Recupera Password
Home Page
Stanze Forum
SQL Server 2000/2005/2008, Express, Access, MySQL, Oracle
Come impostare una Query
mercoledì 05 maggio 2010 - 17.55
Elenco Threads
Stanze Forum
Aggiungi ai Preferiti
Cerca nel forum
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
mer 5 mag 2010 - 17:55
Salve a tutti.
Ho una tabella con i record siffatti:
campo1=INIZIO tipo=DATA
campo2=FINE tipo=DATA
campo3=MSG tipo=TESTO
che rappresenta una raccolta di eventi provenienti da una macchina utensile (allarmi e messaggi).
Il periodo di interrogazione può essere lungo fino a 40 giorni (es.: 1/03 - 31/03).
Però io dovrei 'sovrapporre' al periodo scelto dall'utente una 'maschera' temporale che definisce i turni lavorativi,
ad es.: 8.00 - 12.00 , 14.00 - 18.00 da lunedì al venerdì.
Come posso formulare la query? Esiste in SQL una istruzione che mi permette di sovrapporre una maschera temporale così definita?
Grazie a chi vorrà rispondermi.
Ciao, Massimo.
dinoxet
Profilo
| Senior Member
484
messaggi | Data Invio:
mer 5 mag 2010 - 17:58
descrivi un esempio non ho ben capito cosa intendi per sovrapporre.
DINOXET
__________________________________________
impossible is only a word
lbenaglia
Profilo
| Guru
5.625
messaggi | Data Invio:
mer 5 mag 2010 - 20:52
>Come posso formulare la query? Esiste in SQL una istruzione che
>mi permette di sovrapporre una maschera temporale così definita?
Ciao Massimo,
Posta i comandi di CREATE TABLE della tabella, alcune righe di prova (INSERT INTO), alcuni esempi di query con il relativo result set che ti aspetti con i dati indicati.
>Grazie a chi vorrà rispondermi.
Prego.
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
gio 6 mag 2010 - 09:38
Finora, per presentare un risultato al cliente che chiedeva ad es. dati tra il 1 Marzo e il 31 Marzo, facevo la seguente query:
SELECT * FROM I_TABELLA
WHERE (FINE > '2010/03/01') AND (INIZIO < '2010/03/31')
In tal modo erano selezionati tutti i record compresi e a cavallo degli estremi temporali.
Ora devo complicare le cose perchè occorre tenere conto degli orari di lavoro.
Ovviamente dal 1 al 31 non tutte le ore sono lavorative e quindi i record (che possono coprire anche orari non lavorativi,
perchè un allarme macchina può coprire più turni, ma nelle ore non lavorative non deve essere conteggiato il tempo
ai fini del calcolo dell'efficienza di machina) devono essere 'spurgati' del tempo che non cade negli orari di lavoro.
Quindi, se un allarme è descritto così: INIZIO=9/03/2010 11:10 FINE=9/03/2010 15:45 MSG=MANCA OLIO, la query
deve dare un resultset in cui questo record compare così (in questo caso diventano 2):
INIZIO=9/03/2010 11:10 FINE=9/03/2010 12:00 MSG=MANCA OLIO
INIZIO=9/03/2010 14:00 FINE=9/03/2010 15:45 MSG=MANCA OLIO
perchè devo applicare una 'maschera' temporale data dall'orario di lavoro 8.00 - 12.00 e 14.00 - 18.00
Spero di essermi spiegato.
Grazie.
Jok83
Profilo
| Junior Member
139
messaggi | Data Invio:
gio 6 mag 2010 - 12:46
Ciao
>campo1=INIZIO tipo=DATA
>campo2=FINE tipo=DATA
>INIZIO=9/03/2010 11:10 FINE=9/03/2010 12:00 MSG=MANCA OLIO
>INIZIO=9/03/2010 14:00 FINE=9/03/2010 15:45 MSG=MANCA OLIO
Ma i campi INIZIO e FINE sono Data o DataTime?
Per raddoppiare il record come nell'esempio che dici tu forse si potrebbe fare una Union tra due select (una con gli orari di mattino (di inizio) e l'altra con quelli pomeridiani chiusi nella giornata)
se metti un esempio di creazione e popolazione della tabella magari proviamo a vedere se funziona.
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
gio 6 mag 2010 - 14:28
Grazie della risposta. Non volevo entrare troppo nel dettaglio per non appesantire il thread.
In azienda utilizziamo tabelle Paradox e ambiente di sviluppo Delphi (Windows XP e Vista).
La tabella viene generata da codice mediante componenti nativi Delphi.
I campi INIZIO e FINE son di tipo TDateTime (Data e Ora).
La popolazione della tabella viene eseguita da un applicativo, sempre tramite codice Delphi,
utilizzando il BDE; una cosa del tipo:
with ATable do begin //ATable è il componente per accedere a una tabella
if not Active then Active := True;
Append;
FieldByName('MSG').AsString := MEA.Msg; //MEA è un buffer di dati
FieldByName('INIZIO').AsDateTime := MEA.DataBegin;
FieldByName('FINE').AsDateTime := MEA.DataEnd;
Post;
end;//with
La lettura dei dati invece viene fatta da due nuovi applicativi, sviluppati da me, un Server e un Client.
Il Server legge i dati tramite un componente Delphi TQuery, nella cui proprietà SQL viene impostata
la stringa SQL da eseguire, quella che vi ho mostrato nel post precedente. Alla chiamata del metodo Open
di TQuery viene fornito il resultset.
Forse non ho capito il tuo suggerimento, ma nel mio caso dovrei fare 2*N Union? Ammesso che i turni lavorativi
siano solo 2! Da notare che le date sono 'assolute', comprendono anche l'ora e sono conteggiate con un numero
a 8 byte, la cui origine è il 1° gen 1900.
Penso comunque che l'SQL nativo non contenga una istruzione semplice per fare quello di cui ho bisogno, ma chissà...
Grazie dell'interessamento, Massimo.
Jok83
Profilo
| Junior Member
139
messaggi | Data Invio:
gio 6 mag 2010 - 15:54
Allora non sono sicuro d'aver capito bene e neanche che funzioni sulla tua piattaforma...
ho fatto una prova su un mio database di assistenze e trasportato sul tuo diventa così:
A- prendo tutti i "guasti" compresi in un orario di un giorno (il mio orario è 8-13 14-18) percui tutto ciò che fuori da questo orario per il giorno 05/05/2010 non lo pesco
select * from TUATABELLA
where ((DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13) or
(datepart(hour,INIZIO)>14 and datepart(hour,INIZIO)<18 ))
and convert(date,INIZIO)=convert(date,'05/05/2010')
B - prendo tutti i guasti che sono iniziati nell'orario del mattino e terminati in quello pomeridiano
select * from TUATABELLA where DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13 and convert(date,INIZIO)=convert(date,'05/05/2010')and DATEPART(hour,FINE)>13
C - UNISCO A E B mantenendo i record duplicati
select * from TUATABELLA
where ((DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13) or
(datepart(hour,INIZIO)>14 and datepart(hour,INIZIO)<18 ))
and convert(date,INIZIO)=convert(date,'05/05/2010')
UNION ALL
select * from TUATABELLA where DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13 and convert(date,INIZIO)=convert(date,'05/05/2010')and DATEPART(hour,FINE)>13
prova a vedere se funziona...
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
gio 6 mag 2010 - 17:48
Ti ringrazio moltissimo, domani sono in cassa integrazione, ma lunedì provo subito;
spero di riuscire a convertire le funzioni perchè il Paradox è proprio scarso...
Grazie e buon week-end, Massimo.
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
lun 10 mag 2010 - 11:09
Grazie per la risposta.
Però a me occorre che i record, nel caso cadano a cavallo di due turni, siano 'ritagliati',
come ho mostrato nel mio secondo intervento (a questo punto, penso che ciò debba essere
fatto al momento della generazione dei record in modo da trovarsi la tabella già pronta);
inoltre il cliente può richiedere i dati anche fino a 40 giorni per cui dovrei eliminare
dalla query di esempio da te inviata la parte
and convert(date,INIZIO)=convert(date,'05/05/2010')
in modo da raccogliere i dati su più giorni.
Se sei ancora disponibile, cosa ne pensi?
Ciao, Massimo.
Jok83
Profilo
| Junior Member
139
messaggi | Data Invio:
lun 10 mag 2010 - 12:04
>Grazie per la risposta.
>Però a me occorre che i record, nel caso cadano a cavallo di due turni, siano 'ritagliati',
>come ho mostrato nel mio secondo intervento (a questo punto, penso che ciò debba essere
>fatto al momento della generazione dei record in modo da trovarsi la tabella già pronta);
Ciao,
intendi che deve cambiare l'ora di INIZIO- FINE? come fai vedere qui:
>INIZIO=9/03/2010 11:10 FINE=9/03/2010 12:00 MSG=MANCA OLIO
>INIZIO=9/03/2010 14:00 FINE=9/03/2010 15:45 MSG=MANCA OLIO
>inoltre il cliente può richiedere i dati anche fino a 40 giorni per cui dovrei eliminare
>dalla query di esempio da te inviata la parte
>and convert(date,INIZIO)=convert(date,'05/05/2010')
>in modo da raccogliere i dati su più giorni.
certo qui puoi mettere l'intervello che ti richiedono as esempio da 01 al 31 maggio diventa:
and ((convert(date,INIZIO)>=convert(date,'01/05/2010'))AND(convert(date,INIZIO)<=convert(date,'31/05/2010')))
>Se sei ancora disponibile, cosa ne pensi?
Si non sono sicuro che la soluzione che ti sto proponendo sia la migliore o la più adatta al tuo caso (non sono un esperto)...probabilmente ci stiamo adattando alla situazione che hai, fammi fare una prova sul mio db.
le query che ti ho passato riesci a farle girare sul tuo sitema cmq giusto?
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
lun 10 mag 2010 - 15:30
>Ciao,
>intendi che deve cambiare l'ora di INIZIO- FINE? come fai vedere qui:
>>INIZIO=9/03/2010 11:10 FINE=9/03/2010 12:00 MSG=MANCA OLIO
>>INIZIO=9/03/2010 14:00 FINE=9/03/2010 15:45 MSG=MANCA OLIO
Esatto.
>le query che ti ho passato riesci a farle girare sul tuo sitema cmq giusto?
Non ho nemmeno provato perchè con una SELECT non riesco ad ottenere i
record modificati, dovrei generare prima una tabella o vista e poi usarli,
comunque sì, penso che riuscirei a convertirla per Paradox.
Grazie comunque del tuo gentile supporto.
Massimo.
Jok83
Profilo
| Junior Member
139
messaggi | Data Invio:
lun 10 mag 2010 - 16:18
Allora proviamo:
' per modificare l'ora uso un case when sulla fine nella prma query e sull'inizio nella seconda, ho sostituito i campi con i tuoi spero di non aver fatto confusione perchè non ho modo di provarla sul tuo db:
select INIZIO as INIZIO,case when datepart(hour,FINE)>13 then convert(nvarchar(50),(Convert(date,FINE,1)))+' ' + '13:00:00' else FINE end as FINE,MSG from TUATABELLA
where ((DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13) or
datepart(hour,INIZIO)>14 and datepart(hour,INIZIO)<18 ) and convert(date,INIZIO)=convert(date,'05/05/2010')
UNION ALL
select case when datepart(hour,FINE)>13 then convert(nvarchar(50),(Convert(date,INIZIO,1)))+' ' + '14:00:00' else INIZIO end as INIZIO,FINE AS FINE ,MSG from TUATABELLA
where DATEPART(hour,INIZIO)>8 and DATEPART(hour,INIZIO)<13 and convert(date,INIZIO)=convert(date,'05/05/2010')and DATEPART(hour,FINE)>13
io l'ho provata su un mio db dove ho una tabella che racchiude le richieste di assistenza (SEDE,DATARICHIESTA (il tuo inizio),datachiusuta(la tua FINE):
select CodPT,DataOraRichiesta as INIZIO,case when datepart(hour,DataOraChiusura)>13 then convert(nvarchar(50),(Convert(date,dataorarichiesta,1)))+' ' + '13:00:00' else DataOraChiusura end as FINE from rcaassistenza
where ((DATEPART(hour,dataorarichiesta)>8 and DATEPART(hour,dataorarichiesta)<13) or
datepart(hour,dataorarichiesta)>14 and datepart(hour,dataorarichiesta)<18 ) and convert(date,DataOraRichiesta)=convert(date,'05/05/2010')
UNION ALL
select CodPT,case when datepart(hour,DataOraChiusura)>13 then convert(nvarchar(50),(Convert(date,dataorarichiesta,1)))+' ' + '14:00:00' else DataOraChiusura end as INIZIO,DataOraChiusura AS FINE from rcaassistenza
where DATEPART(hour,dataorarichiesta)>8 and DATEPART(hour,dataorarichiesta)<13 and convert(date,dataorarichiesta)=convert(date,'05/05/2010')and DATEPART(hour,DataOraChiusura)>13
ORDER BY CodPT
e ottengo questo:
SEDE INIZIO FINE
an2 2010-05-05 12:26:27 2010-05-05 13:00:00
an2 2010-05-05 14:00:00 2010-05-05 17:50:46
br1 2010-05-05 15:06:15 2010-05-05 13:00:00
cl1 2010-05-05 15:26:36 2010-05-05 17:00:00
cr1 2010-05-05 09:44:53 2010-05-05 13:00:00
cr1 2010-05-05 14:00:00 2010-05-05 17:23:41
in pratica an2 è iniziato alle 12:26 e finito alle 17:50
e cr1 è iniziato alle 9:44 e finito alle 17:23 mentre br1 e cl1 si sono chiusi nell'arco del turno.
ora rova a lanciarla sul tuo e dimmi se ti da errori e se ti torna qualcosa...
maxbolz
Profilo
| Newbie
7
messaggi | Data Invio:
lun 10 mag 2010 - 17:44
Caro Jok83, sei gentilissimo; non è facile trovare persone come te.
Purtroppo qui siamo costretti a usare Paradox, il cui sviluppo è stato
fermato 20 anni fa' circa e quindi non possiede costrutti del tipo
'case when'; supporta solo un set minimale di SQL92.
Inoltre, poichè i nostri clienti possono definire turni molto variabili
(chi due, chi tre, chi lavora in modo continuato), penso che la soluzione
sia proprio quella di costruire i record ad hoc man mano che viene popolata
la tabella, in modo che la query di raccolta dati tenga solo in considerazione
il range temporale di ispezione selezionato dal cliente.
Dal punto di vista della velocità, l'applicativo di raccolta dati dal campo non ha
problemi a costruire una ulteriore tabella con i dati già 'ritagliati'.
Penso che questa sia la soluzione migliore, a meno di non cambiare il motore DB.
Di nuovo 1000 grazie per la tua disponibilità e auguri per il tuo lavoro.
Ciao, Massimo.
Jok83
Profilo
| Junior Member
139
messaggi | Data Invio:
mar 11 mag 2010 - 09:38
Purtroppo non conosco per nulla Paradox non ho altre vie, però se riesci a risolvere nell'inserimento è sicuramente la soluzione più congeniale.
Magari qualcuno più in gamba tra un pò ti posta una soluzione ancora più efficace...
Ciao e Buon Lavoro!
Torna su
Stanze Forum
Elenco Threads
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?
Dopo esserti registrato potrai chiedere
aiuto sul nostro
Forum
oppure aiutare gli altri
Consulta le
Stanze
disponibili.
Registrati ora !