2012-09-06 12 views
5

Tengo cientos de miles de puntos de precio que abarcan 40 años más. Me gustaría construir una consulta que solo devuelva 3000 puntos de datos totales, siendo los últimos 500 los puntos de datos más recientes y los otros 2500 solo una muestra del resto de los datos, distribuidos uniformemente.Seleccione una porción de gran cantidad de datos en el tiempo con MySQL

¿Es posible hacer esto en una consulta? ¿Cómo seleccionaría solo una muestra de la gran cantidad de datos? Este es un pequeño ejemplo de lo que quiero decir para conseguir sólo una muestra de los otros puntos de datos 2500:

1 
2 
3  
4 
5 
6 
7 
8 
9 
10 

Y quiero volver algo como esto:

1 
5 
10 

Aquí está la consulta para el último 500:

SELECT * FROM price ORDER BY time_for DESC LIMIT 500 

No estoy seguro de cómo obtener los datos de muestra de otros puntos de datos.

+0

¿Puedes mostrar el diseño de la tabla? ¿Y cuántos registros tienes? – Nin

Respuesta

5

Prueba esto:

(SELECT * FROM price ORDER BY time_for DESC LIMIT 500) 
UNION ALL 
(SELECT * FROM price WHERE time_for < (SELECT time_for FROM price ORDER BY time_for LIMIT 500, 1) ORDER BY rand() LIMIT 2500) 
ORDER BY time_for 

Nota: Es probable que va a ser lento. ¿Qué tan grande es esta mesa?

Puede ser más rápido obtener únicamente el ID principal de todas estas filas, y luego unirlo al original en una consulta secundaria una vez que se ha reducido. Esto es porque ORDER BY rand() LIMIT tiene que ordenar toda la tabla. Si la tabla es grande, puede tomar mucho tiempo y mucho espacio en disco. Recuperar solo la ID reduce el espacio de disco necesario.

3

La respuesta anterior es buena, pero especificó que desea que los resultados sean distribuidos uniformemente, así que agregaré esta posibilidad también. Al iterar un contador sobre las filas, puede usar un operador MOD para muestrear una distribución uniforme. No tengo una instalación MYSQL en este momento para probar esto, así que me disculpo si la sintaxis no es 100% exacta. Pero debe ser lo suficientemente cerca y puede darte algunas ideas.

( SELECT p1.* 
     FROM price p1 
    ORDER BY p1.time_for DESC 
     LIMIT 500 ) 

    UNION ALL 

    ( SELECT @i := @i + 1 AS row_num, 
      p2.* 
     FROM price p2, 
      (SELECT @i: = 0) 
     WHERE row_num > 500 
     AND (row_num % 500) = 0 
    ORDER BY time_for DESC ) 

La primera consulta proporciona las 500 filas más recientes. La segunda consulta da cada fila 500 después de eso, devolviendo así una distribución uniforme del resto de los datos. Obviamente, puede ajustar este parámetro para lograr el espaciado de muestra deseado. O base en el número total de filas en la tabla para calcular el espaciado necesario para dar exactamente 2500 registros.

Cuestiones relacionadas