Newsgroup: it.comp.software.database
Titolo: Differenza orari con sqlserver...

Ciao a tutti,
ho un form 
asp.net
 nel quale inserisco degli orari e memorizzo gli orari 
stessi in un db sql server in campi "smalldatetime". Impostando solo l'ora 
il valore del campo sarà del tipo "data odierna - orario".
Quindi devo calcolare la differenza degli orari inseriti e mi piacerebbe 
farlo con una query... se però sottraggo i campi 
"campo1-campo2-campo3-campo4" ho un errore... è possibile che possa solo 
acquisirli via codice trasformarli in secondi e sottrarli, per poi 
trasformarli in orario...?
Grazie... 

"R@" <r@r.r> ha scritto nel messaggio
news:Iej2e.26422$kC3....@tornado.fastwebnet.it...

no, puoi benissimo fare la differenza direttamente in Sql.
Il problema potrebbe essere generato dal fatto che il tipo di dato
smalldatetime ha un delta di valori che va dal 1° gennaio 1900 al 6 giugno
2079.
Quindi se la differenza tra due campi va in negativo (minore del 1/1/1900)
ti viene notificato l'errore di overflow.
Potresti convertire la sottrazione nel tipo datetime
-------------
convert(datetime,Campo1)- convert(datetime,Campo2)- convert(datetime,Campo3)
-------------
estendendo il delta di valori supportati dal 1° gennaio 1753 al 31 dicembre
9999
Ciao Giorgio

 -------------
Forse non è questo il problema... ho comunque errore...
Arithmetic overflow error converting expression to data type datetime.
Grazie. 

 Grazie.
Prego.
Ciao!
-- 
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://mvp.support.microsoft.com
http://italy.mvps.org

 problema.
Proprio come indicatomi:
select 
convert(DATETIME,o_a)-convert(DATETIME,o_p)-convert(DATETIME,t_pause)-convert(DATETIME,t_nong)
from table
dove i 4 campi sono di tipo smalldatetime.
Grazie.

 Grazie.
A te.



ciao,
dipende anche da cosa contengono i campi...
Se contengono solo la parte ora  ..
Ad es.
Campo1= '19000101 15:00:00'
Campo2= '19000101 01:00:00'
Campo3= '19000101 01:00:00'
Campo4= '19000101 01:00:00'
L'espressione Campo1-Campo2-Campo3 risulterà uguale a '19000101 12:00'
ovvero le ore 15:00 - 3 ore
Se invece i campi contengono anche la parte data
Ad es
Campo1= '20050330 15:00:00'
Campo2= '20050330 01:00:00'
Campo3= '20050330 01:00:00'
Campo4= '20050330 01:00:00'
L'espressione Campo1-Campo2-Campo3 anche convertita in datetime genererà
errore perchè
Campo1-Campo2='19000101 14:00:00'
se a questo risultato si sottrae campo3 otteniamo una data con anno 105
avanti Cristo non gestito da Sql Server.
tutto dipende da come memorizzi le ore.
Ciao Giorgio

> tutto dipende da come memorizzi le ore.
E come potrei memorizzarle?
A me la data non interessa, ma mi memorizza quella corrente... mica posso 
farla sparire?
Come posso fare?
Grazie. 

> CREATE TABLE....
Spero di indovinare:
CREATE TABLE [dbo].[tabledis] (
 [id_d] [int] IDENTITY (1, 1) NOT FOR REPLICATION  NOT NULL ,
 [id_viaggio] [int] NULL ,
 [o_p] [datetime] NULL ,
 [o_a] [datetime] NULL ,
 [t_pause] [datetime] NULL ,
 [t_carico1] [datetime] NULL ,
 [n_cons1] [int] NULL ,
 [t_scarico1] [datetime] NULL ,
 [t_carico2] [datetime] NULL ,
 [n_cons2] [int] NULL ,
 [t_scarico2] [datetime] NULL ,
 [t_carico3] [datetime] NULL ,
 [n_cons3] [int] NULL ,
 [t_scarico3] [datetime] NULL ,
 [t_nong] [datetime] NULL ,
 [km_d] [int] NULL ,
 [note_d] [varchar] (255) COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY] 

 CREATE TABLE [dbo].[tabledis] (
...
Mancano i dati :-(


> Mancano i dati :-(
Delimitati dalla virgola:
16,33,2005-03-11 00:00:00,2005-03-11 00:00:00,2005-03-11 00:00:00,2005-03-11 
00:00:00,0,2005-03-11 00:00:00,2005-03-11 00:00:00,0,2005-03-11 
00:00:00,2005-03-11 00:00:00,0,2005-03-11 00:00:00,2005-03-11 00:00:00,0,""
17,35,2005-03-15 15:00:00,2005-03-15 16:00:00,2005-03-15 00:00:00,2005-03-15 
00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,2005-03-15 
00:00:00,2005-03-15 00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,""
18,35,2005-03-15 08:00:00,2005-03-15 16:00:00,2005-03-15 01:00:00,2005-03-15 
00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,2005-03-15 
00:00:00,2005-03-15 00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,""
19,35,2005-03-15 00:00:00,2005-03-15 00:00:00,2005-03-15 00:00:00,2005-03-15 
00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,2005-03-15 
00:00:00,2005-03-15 00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,""
20,35,2005-03-15 00:00:00,2005-03-15 00:00:00,2005-03-15 00:00:00,2005-03-15 
00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,2005-03-15 
00:00:00,2005-03-15 00:00:00,0,2005-03-15 00:00:00,2005-03-15 00:00:00,0,""
21,38,2005-03-23 00:00:00,2005-03-23 00:00:00,2005-03-23 00:00:00,2005-03-23 
02:00:00,0,2005-03-23 00:00:00,2005-03-23 00:00:00,0,2005-03-23 
00:00:00,2005-03-23 00:00:00,0,2005-03-23 00:00:00,2005-03-23 
00:00:00,399,""

 Grazie.
Prego.
Ciao!


 oraria in uno dei seguenti formati:
Sto facendo delle prove, ma perché le sottrazioni funzionano con 
"1900-01-01" (è pur sempre una data), e non se tutti i campi hanno data 
"2005-03-30" ???


E' molto semplice.
USE tempdb
GO
/* Definisco la tabella dbo.Times */
CREATE TABLE dbo.Times(
TimeID int NOT NULL IDENTITY PRIMARY KEY,
Time1 smalldatetime NOT NULL,
Time2 smalldatetime NOT NULL,
Time3 smalldatetime NOT NULL,
Time4 smalldatetime NOT NULL
)
GO
/* La popolo */
SET NOCOUNT ON
INSERT dbo.Times VALUES('20050330 23:59:05', '20050330 00:00:10', '20050330
01:02', '20050330 03:12:24')
INSERT dbo.Times VALUES('20050330 22:00:00', '20050330 00:00:36', '20050330
04:09', '20050330 00:27:36')
INSERT dbo.Times VALUES('20050330 11:04:49', '20050330 00:40:00', '20050330
03:06', '20050330 00:18:00')
SET NOCOUNT OFF
GO
/* Vediamo */
SELECT *
FROM dbo.Times
GO
/* Output:
TimeID Time1                Time2                Time3                Time4
------ -------------------- -------------------- -------------------- ------
--------------
1      2005-03-30 23:59:00  2005-03-30 00:00:00  2005-03-30 01:02:00
2005-03-30 03:12:00
2      2005-03-30 22:00:00  2005-03-30 00:01:00  2005-03-30 04:09:00
2005-03-30 00:28:00
3      2005-03-30 11:05:00  2005-03-30 00:40:00  2005-03-30 03:06:00
2005-03-30 00:18:00
*/
/* Sottrazione */
SELECT Time1 - Time2
FROM dbo.Times
GO
/* Output:
Time
--------------------
1900-01-01 23:59:00
1900-01-01 21:59:00
1900-01-01 10:25:00
*/
Come *SICURAMENTE* avrai letto dai link che ti ho passato, ora saprai che il
range di validità del data type smalldatetime è compreso tra l'1 gennaio
1900 ed il 6 giugno 2079 e che le informazioni data e ora sono memorizzate
in 2 coppie di interi di 2 bytes:
- i primi 2 per la memorizzazione dei giorni dopo l'1 gennaio 1900
- gli altri 2 per la memorizzazione dei minuti dopo la mezzanotte
Ora, sottraendo Time1 con Time2, noterai che la prima coppia di byte (quella
della data) si annulla (vale 0) ottenendo la base date (1 gennaio 1900).
Se alla base date vai a sottrarre Time3, la cui data è il 30 marzo 2005 (in
intero 38439, ovvero 38439 giorni dopo l'1 gennaio 1900), andrai fuori dal
range di validità (0 - 38439 = -38439) del data type ottenendo l'Arithmetic
overflow.
La soluzione più pulita sarebbe quella di memorizzare SOLO l'informazione
oraria, ma se per qualche motivo che ignoro vuoi memorizzare anche la data,
allora devi fare attenzione ad eliminarla prima di eseguire la sottrazione:
/* Sottrazione */
SELECT CAST(CONVERT(char(8), Time1, 108) AS smalldatetime) -
       CAST(CONVERT(char(8), Time2, 108) AS smalldatetime) -
       CAST(CONVERT(char(8), Time3, 108) AS smalldatetime) -
       CAST(CONVERT(char(8), Time4, 108) AS smalldatetime) AS [Time]
FROM dbo.Times
GO
/* Output:
Time
--------------------
1900-01-01 23:59:00
1900-01-01 21:59:00
1900-01-01 10:25:00
*/
/* Se voglio recuperare solo l'informazione oraria... */
SELECT
CONVERT(char(8), CAST(CONVERT(char(8), Time1, 108) AS smalldatetime) -
                 CAST(CONVERT(char(8), Time2, 108) AS smalldatetime) -
                 CAST(CONVERT(char(8), Time3, 108) AS smalldatetime) -
                 CAST(CONVERT(char(8), Time4, 108) AS smalldatetime)
, 108) AS [Time]
FROM dbo.Times
GO
/* Output:
Time
-------- 
19:45:00
17:22:00
07:01:00
*/
Inoltre ti faccio notare che la precisione del data type smalldatetime è al
minuto, quindi i secondi sono ignorati.
