tipo obtener fecha entre diferencia dato convertir convert sql sql-server sql-server-2008 date

obtener - tipo de dato date sql



Comparaciones de fechas de SQL Server basadas únicamente en meses y años (4)

Tengo problemas para determinar la mejor forma de comparar fechas en SQL en función del mes y el año solamente.

Hacemos cálculos basados ​​en fechas y dado que la facturación ocurre mensualmente, la fecha del mes ha causado más obstáculos.

Por ejemplo

DECLARE @date1 DATETIME = CAST(''6/15/2014'' AS DATETIME), @date2 DATETIME = CAST(''6/14/2014'' AS DATETIME) SELECT * FROM tableName WHERE @date1 <= @date2

El ejemplo anterior no devolverá ninguna fila ya que @ date1 es mayor que @ date2. Entonces me gustaría encontrar una manera de sacar el día de la ecuación.

Del mismo modo, la siguiente situación me causa dolor por la misma razón.

DECLARE @date1 DATETIME = CAST(''6/14/2014'' AS DATETIME), @date2 DATETIME = CAST(''6/15/2014'' AS DATETIME), @date3 DATETIME = CAST(''7/1/2014'' AS DATETIME) SELECT * FROM tableName WHERE @date2 BETWEEN @date1 AND @date3

He hecho conversiones en línea de las fechas para derivar el primer día y el último día del mes para la fecha especificada.

SELECT * FROM tableName WHERE date2 BETWEEN DATEADD(month, DATEDIFF(month, 0, date1), 0) -- The first day of the month for date1 AND DATEADD(s, -1, DATEADD(mm, DATEDIFF(m, 0, date2) + 1, 0)) -- The lastday of the month for date3

Tiene que haber una manera más fácil de hacer esto. ¿Alguna sugerencia?


Para manejar las desigualdades, como entre, me gusta convertir la fecha / hora a una representación YYYYMM, ya sea como una cadena o un número entero. Para este ejemplo:

DECLARE @date1 DATETIME = CAST(''6/14/2014'' AS DATETIME), @date2 DATETIME = CAST(''6/15/2014'' AS DATETIME), @date3 DATETIME = CAST(''7/1/2014'' AS DATETIME); SELECT * FROM tableName WHERE @date2 BETWEEN @date1 AND @date3;

Escribiría la consulta como:

SELECT * FROM tableName WHERE year(@date2) * 100 + month(@date2) BETWEEN year(@date1) * 100 + month(@date1) AND year(@date3) * 100 + month(@date1);


Primero, usaría un formato para las fechas que no sea ambiguo, como el estándar ''YYYYMMDD'' y no el ''6/15/2014'' que ha estado usando. El blog de Aaron Bertrand explica mucho mejor que yo, las diversas formas en que esto puede ir mal:
Malos hábitos a patear: consultas de rango / fecha incorrectas

Para el problema específico, su última consulta, que encuentra el primer y el último día de los meses (para date1 y date3), en mi opinión está en el camino correcto. Solo necesita los primeros días de meses (el primer día de la fecha1 y el primer día del próximo mes para la fecha3), si evita el mal BETWEEN : ¿Qué tienen en común BETWEEN y el diablo?

SELECT * FROM tableName WHERE date2 >= DATEADD(month, DATEDIFF(month, ''19000101'', @date1), ''19000101'') AND date2 < DATEADD(month, 1+DATEDIFF(month, ''19000101'', @date3), ''19000101'') ;

La consulta funciona tal como está, sin importar el tipo de datos de date2 ( DATE , DATETIME , DATETIME2 o SMALLDATTEIME ).

El optimizador considerará los puntos de bonificación, los índices en date2 esta manera.

Mejora, de acuerdo con (aún, otra) publicación de Aaron en el blog, para evitar un problema con la estimación de cardinalidad al evaluar expresiones con DATEDIFF() :
Sorpresas y suposiciones de rendimiento: DATEDIFF

SELECT * FROM tableName WHERE date2 >= CONVERT(DATE, DATEADD(day, 1 - DAY(@date1), @date1)) AND date2 < DATEADD(month, 1, CONVERT(DATE, DATEADD(day, 1 - DAY(@date3), @date3))) ;


Puede filtrar el mes y el año de una fecha determinada a la fecha actual así:

SELECT * FROM tableName WHERE month(date2) = month(getdate()) and year(date2) = year(getdate())

Simplemente reemplace el método GETDATE() con la fecha deseada.


Puedes unirte a los valores de MONTH y YEAR de esas fechas:

SELECT * FROM tableName WHERE YEAR(@date1) = YEAR(@date2) AND MONTH(@date1) = MONTH(@date2)