2011-05-17 10 views
7

Buenas tardes, nos preguntábamos cómo eliminar aleatoriamente el 20% de las filas en una tabla sqlite con 15000 filas. Notamos que esta pregunta se resolvió en Stack Overflow usando SQL Server Select n random rows from SQL Server table. Pero la secuencia de comandos de SQL Server no parece funcionar correctamente en sqlite. ¿Cómo podemos convertir el script de SQL Server a un script equivalente a sqlite? Gracias.Cómo eliminar aleatoriamente el 20% de las filas en una tabla SQLite

+0

¿Qué pasa con [la respuesta de Kevin Peno] (https://stackoverflow.com/a/6037746/2932052)? – Wolf

Respuesta

5

Alternativamente, puesto que la función aleatoria() en sqlite devuelve un entero de 64 bits con signo, podemos calcular un punto dentro de este espacio como (2^63) * 0.6. Los enteros con signo mayor a este serán el 40% del conjunto de enteros de 64 bits con signo positivo, por lo que el 20% del conjunto completo.

Truncar al número entero siguiente, esto es 5534023222112865484.

lo tanto, debe ser capaz de obtener el 20% de sus filas con un simple:

SELECT * FROM table WHERE random() > 5534023222112865485 

o en su caso, ya que desea borrar que muchos:

DELETE FROM table WHERE random() > 5534023222112865485 

te esperan disfruta este enfoque En realidad, puede ser adecuado si desea un alto rendimiento de dicha operación, pero puede depender del hardware/de la versión, por lo que probablemente no valga la pena el riesgo.

+0

Gracias por su respuesta. Solo traté de aceptar tu respuesta. Una vez que ejecutemos DELETE FROM tabla WHERE random()> 5534023222112865485, habrá espacios vacíos en los rowids en la tabla. ¿Sabes qué instrucciones sqlite ejecutar para cerrar las lagunas rowid? Gracias. – Frank

+3

Como buena práctica general, no debería preocuparse por los valores reales de ROWID y de si podría haber lagunas en la secuencia. Por diversas razones, la base de datos puede terminar con lagunas en la secuencia en el curso normal de uso en cualquier caso. Por ejemplo, cuando COMIENZA; INSERTAR; INSERTAR; COMETER; en un hilo mientras COMIENZAS; INSERTAR; RETROCEDER; en otro hilo podrías terminar con un hueco en ROWID. – karora

+2

Además, como alguien señala en un comentario a continuación, usando WHERE (random()% 5) = 0 es realmente una mejor solución que la mía, ya que no requiere el cálculo sofisticado del tamaño de un int. De 64 bits , y no tiene el potencial de depender del hardware/versión. – karora

4

No es exactamente "aleatorio", pero si tiene una columna de identidad en la tabla puede DELETE FROM mytable WHERE ID % 5 = 0 que debería eliminar estadísticamente muy cerca de una quinta de las filas.

+0

@Will A, gracias por su respuesta. Acabo de aceptar tu respuesta. La única columna de identidad que tenemos en nuestra tabla es la columna ROWID implícita. ¿Podemos sustituir ROWID FOR ID en su respuesta? Gracias por su sugerencia. – Frank

+0

@Frank - placer, señor. Sí, ROWID estará bien. –

+1

@Frank: puede usar 'rowid'. También podría usar 'WHERE random()% 5 = 0'. –

3

Probar:

DELETE FROM TABLE 
WHERE ROWID IN (SELECT ROWID FROM TABLE ORDER BY RANDOM() LIMIT 3000) 

Si desea calcular el 20% en una subconsulta: LIMIT (SELECT CAST((COUNT(id) * 0.2) AS INT)

+0

@ user589993, gracias por su respuesta. Acabo de aceptar tu respuesta. No tenemos una columna de identificación en nuestra tabla sqlite. ¿Podemos usar ROWID en lugar de ID? Gracias por tu ayuda. – Frank

+0

Sí, ROWID funcionará de la misma manera, y parece que usted aceptó una de las otras soluciones. – garnertb

+0

@ user589993, gracias por su respuesta. Lo intentaré de inmediato y te haré saber nuestros resultados. – Frank

2

SQLite - ORDER BY RAND() proporciona una pista. Por lo tanto, esto puede funcionar?

DELETE FROM table WHERE id IN(
    SELECT id FROM table ORDER BY RANDOM() LIMIT (
     SELECT CAST((COUNT(id) * 0.2) AS INT) FROM table 
    ) 
); 
+0

Gracias por su respuesta. Acabo de aceptar tu respuesta. Podemos sustituir ROWID por ID en su respuesta. Gracias por su asistencia. – Frank

+0

@Frank, sí. solo puedes aceptar una respuesta. –

+0

He intentado tu respuesta. Funciona correctamente Noté que ahora hay lagunas en ROWID. ¿Es posible hacer que los ROWIDs sean contiguos nuevamente? Gracias por tu ayuda. – Frank

Cuestiones relacionadas