2010-03-07 15 views

risposta

12

Do non utilizzare i tipi di carattere per memorizzare le informazioni di data/ora.

In SQL Server 2008, è necessario il tipo time per questo, che è quello che è necessario utilizzare se gli intervalli di tempo sono inferiori a 1 giorno. Nelle versioni precedenti, o se è necessario memorizzare intervalli più grandi, sarà necessario utilizzare datetime o smalldatetime (in base alla precisione necessaria).

Un'altra opzione sarebbe quella di scegliere un'unità di tempo, ad esempio minuti, e utilizzare solo un valore int per rappresentare il numero di unità. Assicurati che (a) l'unità scelta sia effettivamente abbastanza precisa da registrare gli intervalli più piccoli da tracciare, e (b) il tipo numerico effettivo sia abbastanza grande da contenere gli intervalli più grandi che devi tracciare. Un smallint potrebbe essere sufficiente per tenere traccia del numero di minuti in un giorno; d'altra parte, il rilevamento del numero di millisecondi entro un periodo di tempo di 10 anni dovrebbe essere memorizzato come bigint.

5

Basta usare l'intero per memorizzare l'intervallo in secondi. DATEDIFF restituisce intero. Scrivi una funzione che la trasforma in testo. Questo ha bisogno di alcune adjustmens (in modo che mostra "1 min", non "1 min"), ma dovrebbe funzionare bene:

CREATE FUNCTION dbo.SecondsToText(@seconds int) 
RETURNS VARCHAR(100) 
AS 
BEGIN 
    declare @days int; 
    set @days = @seconds/(3600 * 24); 
    declare @hours int; 
    set @hours = (@seconds - @days * 3600 * 24)/3600; 
    declare @minutes int; 
    set @minutes = (@seconds - @days * 3600 * 24 - @hours * 3600)/60; 
    set @seconds = (@seconds - @days * 3600 * 24 - @hours * 3600 - @minutes * 60); 
    RETURN 
    RTRIM(CASE WHEN @days > 0 THEN CAST(@days as varchar) + ' days ' ELSE '' END + 
    CASE WHEN @hours > 0 THEN CAST(@hours as varchar) + ' hours ' ELSE '' END + 
    CASE WHEN @minutes > 0 THEN CAST(@minutes as varchar) + ' minutes ' ELSE '' END + 
    CASE WHEN @seconds > 0 THEN CAST(@seconds as varchar) + ' seconds ' ELSE '' END) 
END 
GO 
2

Dipende dal vostro intervallo di tempo - o la conversione di tutto per pochi secondi e solo memorizzare tale valore come INT, o se il tuo intervallo di tempo è più grande, potresti voler utilizzare i campi per ore, minuti, secondi separatamente.

Inoltre, SQL Server 2008 introduce un nuovo TIME data type che consente di memorizzare valori di solo orario.

2

Come detto @Aaronaught utilizzare un tipo di dati data/ora o datetime (se necessario) per memorizzare i valori; ma questi tipi archiviano solo un'istanza in tempo e non un intervallo di tempo o durata. Dovrai utilizzare due campi per memorizzare un intervallo, ad es. [time_span_start] e [time_span_end]. La differenza tra i due ti darà l'intervallo.

La risposta più lunga alla tua domanda può essere risolta scaricando una copia di "Sviluppo di applicazioni database orientate al tempo in SQL" di Richard T. Snodgrass. E 'liberamente disponibile in formato PDF, date un'occhiata qui:

http://www.cs.arizona.edu/~rts/publications.html

0

correlati alla risposta di Tony, è anche possibile utilizzare una sola colonna datetime rispetto ad un tempo di avvio standard che è implicito per tutti gli intervalli - per esempio: 1/1/1900 12:00 AM.

In questo caso è facile abbastanza per lo stoccaggio:

INSERT INTO tbl (interval) VALUES (DATEADD(s, '1/1/1900', DATEDIFF(s, @starttime, @endtime)) 

Ora, questo non è ovviamente facile per fare somme di righe, così si potrebbe pensare di aggiungere persistito colonna calcolata (s) di DATEDIFF (s, '1/1/1900', intervallo) per fornire secondi per eseguire SUM.

Ora, qui è dove si fa interessante per SQL Server:

A causa di implementazione di SQL Server per la conversione dei numeri da e per date, 0 -> 1/1/1900 12:00, 0.5 -> 1/1/1900 12:00 PM, 1 -> 1/2/1900 12:00 AM ecc. Ovvero il numero intero viene considerato come il numero di giorni dall'1/1/1900 e la parte frazionaria è la frazione all'interno del giorno. Quindi puoi in realtà ingenuamente aggiungerli per ottenere un intervallo.

E infatti:

SELECT CONVERT(DATETIME, 1) + CONVERT(DATETIME, 0) + CONVERT(DATETIME, 2) + CONVERT(DATETIME, 0.5) 

dà '1900/01/04 12: 00: 00.000' come previsto

Così si può fare questo (andare in giro SUM convertendo):

DECLARE @datetest TABLE (dt DATETIME NOT NULL) 

INSERT INTO @datetest (dt) 
VALUES (0) 
INSERT INTO @datetest (dt) 
VALUES (1) 
INSERT INTO @datetest (dt) 
VALUES (2) 
INSERT INTO @datetest (dt) 
VALUES (0.5) 

SELECT * 
FROM @datetest 

SELECT CONVERT(DATETIME, SUM(CONVERT(FLOAT, dt))) 
FROM @datetest 

Non sto sostenendo di farlo in generale, YMMV, e qualsiasi soluzione di progettazione scelta deve essere verificata rispetto a tutte le vostre esigenze.

Problemi correlati