2010-11-30 44 views
18

Supongamos esta tabla:MySQL: intervalo promedio entre los registros

id date 
---------------- 
1  2010-12-12 
2  2010-12-13 
3  2010-12-18 
4  2010-12-22 
5  2010-12-23 

puedo encontrar los intervalos medios entre estas fechas, el uso de MySQL Cómo consultas solamente?

Por ejemplo, el cálculo de esta tabla será

(
    (2010-12-13 - 2010-12-12) 
    + (2010-12-18 - 2010-12-13) 
    + (2010-12-22 - 2010-12-18) 
    + (2010-12-23 - 2010-12-22) 
)/4 
---------------------------------- 
= (1 DAY + 5 DAY + 4 DAY + 1 DAY)/4 
= 2.75 DAY 
+2

Esto será mucho más fácil sin hacerlo en SQL. ¿Por qué necesita que se haga en SQL? – jwueller

+1

Porque suena como algo divertido de hacer. Ya lo he implementado con mi función PHP. Pero tengo curiosidad por ver si se puede hacer con MySQL sin un golpe de rendimiento significativo. – HyderA

+0

Antes que nada debe calcular la diferencia entre 2 filas: http://stackoverflow.com/questions/3017468 –

Respuesta

35

Intuitivamente, lo que está pidiendo debe ser equivalente al intervalo entre la primera y la última fecha, dividido por el número de fechas menos 1.

Voy a explicar más a fondo. Imagine las fechas son puntos en una línea (+ son las fechas actuales, - son fechas que faltan, la primera fecha es el 12, y me cambió la última fecha a diciembre 24o con fines ilustrativos):

++----+---+-+ 

Ahora, lo que realmente quiere hacer, es espaciar uniformemente las fechas entre estas líneas, y encontrar el tiempo que está entre cada uno de ellos:

+--+--+--+--+ 

para hacer eso, usted simplemente toma el número de días entre la última y la primera días, en este caso 24 - 12 = 12, y divídalo por el número de intervalos que tiene que espaciar, en este caso 4: 12/4 = 3.

Con una consulta de MySQL

SELECT DATEDIFF(MAX(dt), MIN(dt))/(COUNT(dt) - 1) FROM a; 

Esto funciona en esta tabla (con sus valores que devuelve 2.75):

CREATE TABLE IF NOT EXISTS `a` (
    `dt` date NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

INSERT INTO `a` (`dt`) VALUES 
('2010-12-12'), 
('2010-12-13'), 
('2010-12-18'), 
('2010-12-22'), 
('2010-12-24'); 
+2

D'oh, ¡tienes razón! Si solo tiene marcas de tiempo y no pares de inicio/final, no hay necesidad de engaños de agregación. – Dmitri

+4

+1 por no seguir un patrón y ver el problema como realmente es. : D – Unreason

+1

¡Usted señor, es un genio! Esta solución es el ejemplo perfecto de lograr la simplicidad al pensar fuera de la caja. – HyderA

0

Es necesario hacer auto unirse y obtener diferencias utilizando la función DATEDIFF y obtener la media.

+0

No hay una clave principal en la tabla. Entonces, si me inscribo, ¿cómo calculo usando la fila siguiente o anterior? – HyderA

+0

no hay campo único? use la consulta interna –

+0

¡Sí! No me preguntes, no lo diseñé. – HyderA

2

Si los ids se incrementan de manera uniforme sin huecos, unirse a la mesa a sí mismo en ID + 1:

SELECT d.id, d.date, n.date, datediff(d.date, n.date) 
FROM dates d 
JOIN dates n ON(n.id = d.id + 1) 

Entonces GROUP BY y media, según sea necesario.

Si los identificadores no son uniformes, realice primero una consulta interna para asignar identificadores ordenados.

Supongo que también necesitará agregar una subconsulta para obtener el número total de filas.

Alternativamente

Crear una función de agregado que realiza un seguimiento de la fecha anterior, y una suma continua y contar. Todavía deberá seleccionar de una subconsulta para forzar el orden por fecha (en realidad, no estoy seguro de si eso está garantizado en MySQL).

Ahora que lo pienso, esta es una forma mucho mejor de hacerlo.

Y aún más simple

Sólo señalar que la solución de Vegard es mucho mejor.

+0

La alternativa es un buen comienzo, déjame ver qué puedo hacer. – HyderA

1

La siguiente consulta devuelve resultado correcto

SELECT AVG(
     DATEDIFF(i.date, (SELECT MAX(date) 
          FROM intervals WHERE date < i.date) 
       ) 
      ) 
FROM intervals i 

pero se ejecuta una sub consulta dependiente de lo que podría ser muy ineficiente sin índice y en un mayor número de filas.

+1

Bastante ineficiente, tomó aproximadamente 2 segundos para ejecutarse en 100 registros. Pero hace exactamente lo que se supone que debe hacer. ¿Podemos optimizar esto? – HyderA

+0

ancho sub consultas allí siempre estaré el problema con la lentitud. –

Cuestiones relacionadas