Estoy tratando de select every n-th row from mysql , leí esta respuesta .
Hay una tabla sys_request_log :
CREATE TABLE `sys_request_log` ( `id` bigint(20) NOT NULL, `user_id` bigint(20) DEFAULT NULL, `ip` varchar(50) DEFAULT NULL, `data` mediumtext, `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, KEY `user_id` (`user_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;Contiene 11837 filas.
Intento select every 5-th row from table , primero trato de ejecutar:
SELECT * FROM (SELECT @ROW := @ROW + 1 AS rownum, log.* FROM ( SELECT @ROW := 0 ) r, sys_request_log log ) ranked WHERE rownum % 5 = 1El resultado es:
rownum id user_id create_time ------------------------------------------------------------------- 1 1271446699071639552 1 2020-06-12 22:18:10 6 1271446948980854784 1 2020-06-12 22:19:10 11 1271447016878247936 1269884071484461056 2020-06-12 22:19:26Cuesta 1.001s de tiempo
Encontré que hay una columna no relacionada rownum . Así que modifico el SQL así:
SELECT log.* FROM (SELECT @ROW := @ROW + 1 AS rownum FROM (SELECT @ROW := 0) t) r, sys_request_log log WHERE rownum % 5 = 1Ahora el resultado es limpio (sin número de fila), ¡pero cuesta 2.516 s de tiempo!
¿Por qué?
Versión de Mysql: 5.7.26-registro
En el primer caso, los valores del número de fila se seleccionan durante la selección de la tabla ( sys_request_log ), pero en el segundo caso se produce un producto cartesiano entre la subconsulta r y la selección de la tabla debido a la ocurrencia de CROSS JOIN para cada número de fila individual. frente a cada valor de fila individual de la tabla.
Si entiendo correctamente, puede hacer lo que quiera moviendo la asignación de variables a la cláusula where :
select srl.* from sys_request_log srl cross join (select @rn := 0) params where (@rn := (@rn + 1)) % 5 = 1; Tenga en cuenta que esto funciona en este caso, porque la consulta debe realizar un escaneo completo de la tabla y ejecutar la cláusula WHERE en cada fila. Puede que no funcione si la consulta tiene JOIN , GROUP BY u ORDR BY .
El uso de variables de esta manera está obsoleto en MySQL ahora. Debe actualizar y aprender sobre las funciones de la ventana.
Su segunda consulta tiene un resultado diferente al de la primera y devuelve todas las filas, así que tómese mucho más tiempo que la primera.
Para eliminar el número de rownum de la primera consulta, solo nombre los campos en la cláusula SELECT.
prueba esto:
SELECT ranked.id, ranked.user_id ,ranked.create_time FROM ( SELECT @ROW := @ROW + 1 AS rownum, log.* FROM ( SELECT @ROW := 0 ) r, sys_request_log log ) ranked WHERE rownum % 5 = 1