una tipo obtener mes manejo insertar hora fechas fecha ejemplo dato año sql sql-server tsql

tipo - Fecha MS SQL solo sin tiempo



obtener mes y año de una fecha sql (12)

Pregunta

Hola a todos,

He tenido cierta confusión durante bastante tiempo con el uso de un tipo de SQL DateTime usando T-SQL. Esencialmente, quiero tomar un valor de DateTime de, por ejemplo, 2008-12-1 14:30:12 y hacerlo 2008-12-1 00:00:00. Muchas de las consultas que ejecutamos para los informes usan un valor de fecha en la cláusula WHERE, pero o bien tengo un valor de fecha de inicio y fin de un día y uso un BETWEEN, o encuentro otro método.

Actualmente estoy usando lo siguiente: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

Sin embargo, esto parece un poco torpe. Esperaba que hubiera algo más simple como CAST([tstamp] AS DATE)

Algunos sitios en línea recomiendan usar la función DATEPART (), pero luego termino con algo como esto:

WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam) AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam) AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam)

Tal vez estoy demasiado preocupado por algo pequeño y, si es así, házmelo saber. Solo quiero asegurarme de que lo que estoy escribiendo sea lo más eficiente posible. Quiero eliminar cualquier enlace débil.

¿Alguna sugerencia?

Gracias,
do

Solución

Gracias a todos por los excelentes comentarios. Mucha información útil. Voy a cambiar nuestras funciones para eliminar la función en el lado izquierdo del operador. Aunque la mayoría de nuestras columnas de fecha no usan índices, probablemente sea una mejor práctica.


Cuidado aquí, si usa algo largo las líneas de WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam forzará un escaneo en la tabla y no se usarán índices para esa parte.

Una forma mucho más limpia de hacerlo es definir una columna calculada

create table #t ( d datetime, d2 as cast (datepart(year,d) as varchar(4)) + ''-'' + right(''0'' + cast (datepart(month,d) as varchar(2)),2) + ''-'' + right(''0'' + cast (datepart(day,d) as varchar(2)),2) ) -- notice a lot of care need to be taken to ensure the format is comparable. (zero padding) insert #t values (getdate()) create index idx on #t(d2) select d2, count(d2) from #t where d2 between ''2008-01-01'' and ''2009-01-22'' group by d2 -- index seek is used

De esta manera, puede verificar directamente la columna d2 y se usará un índice y no tendrá que perder conversiones.


Las funciones de fecha publicadas por otros son la forma más correcta de manejar esto.

Sin embargo, es divertido que menciones el término "piso", porque hay un pequeño truco que se ejecutará un poco más rápido:

CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)


Sí, T-SQL puede sentirse extremadamente primitivo a veces, y son cosas como estas las que a menudo me empujan a hacer un montón de mi lógica en mi idioma de elección (como C #).

Sin embargo, cuando es absolutamente necesario hacer algunas de estas cosas en SQL por motivos de rendimiento, la mejor opción es crear funciones para alojar estos "algoritmos".

Mira este articulo. Él ofrece bastantes funciones prácticas de SQL en esta línea que creo que te ayudarán.

http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx


eso es muy malo para el rendimiento, eche un vistazo a Solo en una base de datos ¿Puede obtener un 1000% de mejora al cambiar unas pocas líneas de código?

las funciones en el lado izquierdo del operador son malas

Aquí está lo que tú necesitas hacer

declare @d datetime select @d = ''2008-12-1 14:30:12'' where tstamp >= dateadd(dd, datediff(dd, 0, @d)+0, 0) and tstamp < dateadd(dd, datediff(dd, 0, @d)+1, 0)

Ejecuta esto para ver lo que hace

select dateadd(dd, datediff(dd, 0, getdate())+1, 0) select dateadd(dd, datediff(dd, 0, getdate())+0, 0)


Alternativamente podrías usar

declare @d datetimeselect @d = ''2008-12-1 14:30:12'' where tstamp BETWEEN dateadd(dd, datediff(dd, 0, @d)+0, 0) AND dateadd(dd, datediff(dd, 0, @d)+1, 0)


Aquí hay una consulta que devolverá todos los resultados dentro de un rango de días.

DECLARE @startDate DATETIME DECLARE @endDate DATETIME SET @startDate = DATEADD(day, -30, GETDATE()) SET @endDate = GETDATE() SELECT * FROM table WHERE dateColumn >= DATEADD(day, DATEDIFF(day, 0, @startDate), 0) AND dateColumn < DATEADD(day, 1, DATEDIFF(day, 0, @endDate))


¿Qué tal esto?

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)


FWIW, he estado haciendo lo mismo que tu durante años

CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

Me parece que esta es una de las mejores formas de perder tiempo en términos de flexibilidad, velocidad y facilidad de lectura. (lo siento). Algunas funciones UDF como se sugieren pueden ser útiles, pero las UDF pueden ser lentas con conjuntos de resultados más grandes.


CONVERT(date, GETDATE()) y CONVERT(time, GETDATE()) funciona en SQL Server 2008. No estoy seguro acerca de 2005.


WHERE DATEDIFF(day, tstamp, @dateParam) = 0

Esto debería llevarte allí si no te importa el tiempo.

Esto es para responder la meta pregunta de comparar las fechas de dos valores cuando no te importa el tiempo.


DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))

Editar: Si bien esto eliminará la porción de tiempo de su fecha y hora, también hará que la condición no sea SARGABLE . Si eso es importante para esta consulta, una vista indexada o una cláusula between es más apropiada.


Si está utilizando SQL Server 2008 tiene esto incorporado ahora, vea esto en libros en línea

CAST(GETDATE() AS date)