2010-03-07 18 views

Respuesta

12

Do no use los tipos de caracteres para almacenar la información de fecha/hora.

En SQL Server 2008, tiene el tipo time para esto, que es lo que debe usar si los intervalos de tiempo son inferiores a 1 día. En versiones anteriores, o si necesita almacenar intervalos más grandes, tendrá que usar datetime o smalldatetime (dependiendo de la precisión que necesite).

Otra opción sería elegir una unidad de tiempo, por ejemplo, minutos, y simplemente usar un valor int para representar el número de unidades. Solo asegúrate de que (a) la unidad que elijas sea lo suficientemente precisa como para registrar los intervalos más pequeños que necesites rastrear, y (b) el tipo numérico real sea lo suficientemente grande como para contener los intervalos más largos que necesites rastrear. Un smallint podría ser suficiente para rastrear la cantidad de minutos dentro de un día; por otro lado, el seguimiento de la cantidad de milisegundos dentro de un período de 10 años tendría que almacenarse como bigint.

5

Simplemente use un número entero para almacenar el intervalo en segundos. DATEDIFF devuelve un entero. Escribe una función que lo convierta en texto. Éste necesita algunos adjustmens (por lo que muestra "1 min", no "1 '"), pero debería funcionar bien:

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

depende de su rango de tiempo - ya sea convertir todo a segundos y simplemente almacenar ese valor como INT, o si el lapso de tiempo es más grande, es posible que desee utilizar los campos durante horas, minutos, segundos por separado.

Además, SQL Server 2008 presenta un nuevo TIME data type que le permite almacenar valores de solo tiempo.

2

Como @Aaronaught dijo que use una fecha/hora o fecha y hora (según sea necesario) para almacenar sus valores; pero estos tipos solo almacenan una instancia en el tiempo y no un lapso de tiempo o duración. Deberá usar dos campos para almacenar un intervalo, p. [time_span_start] y [time_span_end]. La diferencia entre los dos te dará el intervalo.

La respuesta más larga a su pregunta se puede responder mediante la descarga de una copia de "Desarrollo de aplicaciones de base de datos orientadas en el tiempo en SQL" por Richard T. Snodgrass. Es libremente disponible en formato PDF, echar un vistazo aquí:

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

0

relacionada a la respuesta de Tony, también se puede utilizar una sola columna de fecha y hora en relación con una hora de inicio estándar que está implícito para todos los intervalos - por ejemplo: 1/1/1900 12:00 a.m.

En este caso, es bastante fácil para el almacenamiento:

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

Ahora bien, esto no es obviamente fácil para hacer sumas de filas, por lo que podría pensar en añadir persistido columna calculada (s) de DATEDIFF (s, '1/1/1900', intervalo) para proporcionar segundos para realizar SUM.

Ahora, aquí es donde se pone interesante para SQL Server:

Debido a la implementación de SQL Server para convertir números a y desde fechas, 0 -> 1/1/1900 12:00a.m., 0,5 -> 1/1/1900 12:00 PM, 1 -> 1/2/1900 12:00 AM etc., es decir, el número completo se trata como el número de días desde 1/1/1900 y la parte fraccionaria es la fracción dentro del día. Entonces, de hecho, puedes agregar ingenuamente estos para obtener un intervalo.

Y de hecho:

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

da '04/01/1900 12: 00: 00.000' como se esperaba

Así que usted puede hacer esto (SUMA dando vueltas por la conversión):

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 

No estoy abogando por hacer esto en general, YMMV, y cualquier solución de diseño que elija debe verificarse con todos sus requisitos.

Cuestiones relacionadas