2011-09-13 8 views
5

Estoy escribiendo una pequeña consulta en SQL y estoy a tope con un problema que parece que alguien debe haberse topado antes. Estoy tratando de encontrar la cantidad de meses entre dos fechas. Estoy utilizando una expresión como ...Lucha contra Datediff en SQL

DATEDIFF(m,{firstdate},{seconddate}) 

sin embargo debo advertir que esta función es llevar la cuenta de las veces la fecha cruza el umbral mensual. En el ejemplo ...

DATEDIFF(m,3/31/2011,4/1/2011) will yield 1 
DATEDIFF(m,4/1/2011,4/30/2011) will yield 0 
DATEDIFF(m,3/1/2011,4/30/2011) will yield 1 

¿Alguien sabe cómo encontrar los meses entre dos fechas más, por lo que sobre la base de tiempo transcurrido después veces rebasado el umbral mensual?

+1

Interesante, nunca me di cuenta de eso. – user937146

+1

¿Cuántos días hay en un mes? quieres dados los pares de fechas (2011-03-15, 2011-04-14), (2011-03-15, 2011-04-15), (2011-03-15, 2011-04-16), (2011 -01-28, 2011-02-2 8), (2011-01-28, 2011-03-01), (2012-01-29, 2012-02-28), (2012-01-29, 2012-02-29), (2012-01- 29, 2012-03-01), (2012-01-30, 2012-02-29), (2012-01-30, 2012-03-01), y así sucesivamente.Suele haber una concentración en las fechas de finales de febrero en años bisiestos y años no bisiestos, pero surgen preguntas similares con otras fechas de fin de mes como (2011-05-31, 2011-06-30). –

Respuesta

1
DATEDIFF(m,{firstdate},ISNULL({seconddate},GETDATE())) - CASE 
                 WHEN DATEPART(d,{firstdate}) >= DATEPART(d,ISNULL({seconddate},GETDATE())) 
                 THEN 1 
                 ELSE 0 
+0

http://stackoverflow.com/questions/5131958/datediff-rounding – JBone

+0

El original tiene '>' donde tienes '> =', lo que significa que si las partes del día son iguales, el resultado de DATEDIFF seguirá disminuyendo por 1. Otra cosa es calcular la diferencia de meses entre fechas como '2011-03-31' y' 2011-06-30'. Este método devolverá '2', porque' 31' es de hecho mayor que '30'. Sin embargo, junio no puede tener más de 30 días. Entonces, ¿'2 meses' en este caso está bien? –

+1

Buenos puntos. En este caso, no es excesivamente crítico; sin embargo, en ciertas situaciones puede ser – JBone

2

Si desea encontrar un número nocional de meses, por qué no encuentra la diferencia en días, luego divida entre 30 (elenco a FLOAT según corresponda). O 30.5-ish tal vez, depende de cómo quiera manejar la longitud variable del mes durante todo el año. Pero tal vez ese no sea un factor en su caso particular.

1

Las siguientes declaraciones tienen la misma fecha de inicio y la misma endate. Esas fechas son adyacentes y difieren en el tiempo en .0000001 segundos. La diferencia entre startdate y endate en cada instrucción cruza un calendario o límite de tiempo de su parte de fecha. Cada declaración devuelve 1. ...
SELECCIONAR DATEDIFF (mes, '2005-12-31 23: 59: 59.9999999'
, '2006-01-01 00: 00: 00.0000000'); ....

(de DATEDIFF, sección Límites datepart). Si no está satisfecho con ella, es probable que necesite utilizar como unidad de día según lo propuesto por Martin Clayton

1

DATEDIFF es como este por diseño. Al evaluar una medida de tiempo particular (como meses, o días, etc.), solo considera esa medición y valores más altos, ignorando los más pequeños. Te encontrarás con este comportamiento con cualquier medida de tiempo. Por ejemplo, si usó DATEDIFF para calcular los días, y tuvo una fecha unos segundos antes de la medianoche, y otra fecha unos segundos después de la medianoche, obtendría una diferencia de "1" día, aunque las dos fechas fueron solo algunas segundos separados.

DATEDIFF tiene la intención de dar una respuesta aproximada a las preguntas, así:

Pregunta: ¿Cuántos años tienes? Respuesta: un número entero. Usted no dice "Tengo 59 años, 4 meses, 17 días, 5 horas, 35 minutos y 27 segundos". Solo dices "Tengo 59 años". Ese es el enfoque de DATEDIFF también.

Si desea una respuesta que se adapte a un significado contextual (como su hijo que dice "¡No soy 8! ¡Tengo 8 y 3 cuartos! O soy casi 9!), Entonces debería ver la medición más pequeña siguiente y aproximarse con ella. Por lo tanto, si son los meses que busca, haga un DATEDIFF en días u horas, e intente aproximar meses, sin embargo, parece más relevante para su situación (tal vez quiera respuestas como 1-1/2 meses, o 1.2 meses, etc.) usando CASE/IF-THEN tipos de lógica

+0

. Si cumplió 32 años en diciembre y enero de hoy, no dice que tiene 33 años. Sin embargo, DATEIFF (AÑO) diría que sí lo es. –

+0

@Andriy - fue solo un gran ejemplo. El punto es que no está roto, fue diseñado para dar solo respuestas aproximadas. Tiene un plus-o-minus (límites de error) de 1 (de cualquier medición que esté usando). – Chains

+0

Sí, estoy de acuerdo, es por diseño que funciona de la manera que lo hace. Y estoy de acuerdo en que hay algo común en la forma en que tanto DATEDIFF como las personas tienden a responder aproximadamente, con un entero aproximado. Es solo que DATEDIFF siempre usa las mismas reglas, mientras que las personas no. A veces damos vueltas, como en * veinte minutos pasados ​​cinco *, cuando en realidad solo son dieciocho, y en otros momentos tendemos a reportar un número entero de unidades completas, sin ningún redondeo, como con la edad en años. Y creo que es lo último lo que quiere el OP, la forma de obtener un resultado (un número entero también) * sin * redondeo. –

Cuestiones relacionadas