soporta segundo registros por optimizar numero limitar lentas inner ejemplos eficientes cuantas consultas consulta php mysql sorting

php - segundo - limitar numero de registros en consulta mysql



Actualización del orden de visualización de varias filas de MySQL en una o muy pocas consultas (11)

Agregue un ID (u otra clave) a la tabla, y actualice donde id (o clave) = id (o clave) de la fila modificada.

Por supuesto, tendrá que asegurarse de que no haya valores duplicados de display_order, o que esté bien con los lazos en display_order que se muestran en cualquier orden, o que introducirá un segundo separador de vínculos en la lista orden por orden .

Tengo una tabla con, por ejemplo, 20 filas, cada una con un número para el orden de visualización (1-20).

SELECT * FROM `mytable` ORDER BY `display_order` DESC;

Desde un área de administración, puede arrastrar las filas o escribir manualmente un nuevo número para cada fila.

Seguramente no es bueno pasar por una consulta de ACTUALIZACIÓN para cada fila, ¿cuál es una alternativa en una o muy pocas consultas adecuadas para actualizar una celda en 20 filas o incluso más, 50-200 +?

Edit: Muchas buenas respuestas e ideas. Podría ampliar las ideas que he considerado hasta ahora:

Una cadena de matriz : podría tener el orden en una cadena que enumera las ID de fila únicas en el orden que quiero, por ejemplo, las filas 1,9,2,6,23. Cuando se actualiza el pedido, un campo oculto se actualiza con JavaScript y lo agrega a la base de datos o un archivo de texto cuando se completa:

UPDATE `my_dispaly_order_table` SET `display_order`=''1,9,2,6,23'';

Actualice cada fila individualmente : esto es lo que intentaba evitar, pero solo se cambiaría con poca frecuencia, por lo que 20-30 llamadas en un hit una vez a la semana o al mes podrían no ser un problema, así que simplemente llamar a ACTUALIZAR en cada fila es lo que normalmente uso. hacer:

UPDATE `mytable` SET `display_order`=''1'' WHERE `rowId` = 1; UPDATE `mytable` SET `display_order`=''2'' WHERE `rowId` = 9; UPDATE `mytable` SET `display_order`=''3'' WHERE `rowId` = 2; UPDATE `mytable` SET `display_order`=''4'' WHERE `rowId` = 6; UPDATE `mytable` SET `display_order`=''5'' WHERE `rowId` = 23;


Esta es una excelente manera de clasificar los elementos en una base de datos. Exactamente lo que estaba buscando ;)

Aquí hay una versión mejorada de la versión de Jamon Holmgren. Esta función es totalmente dinámica:

function reOrderRows($tablename, $ordercol, $idsarray){ $query = "UPDATE $tablename SET $ordercol = (CASE $ordercol "; foreach($idsarray as $prev => $new) { $query .= " WHEN $prev THEN $new/n"; } $query .= " END) WHERE $ordercol IN (" . implode(",", array_keys($idsarray)) . ")"; mysql_query($query); }

Esto supone que tiene una columna $ ordercol en su tabla $ nombre de tabla solo para propósitos de pedido.

$ Idsarray es una matriz en la matriz de formato ("current_order_num" => "updated_order_num").

Por lo tanto, si solo desea intercambiar dos líneas en su mesa (imagine que tiene, por ejemplo, los íconos "subir" y "bajar" en su página web), puede usar esta función sobre la anterior:

function swapRows($tablename, $ordercol, $firstid, $secondid){ $swaparray = array("$firstid" => "$secondid", "$secondid" => "$firstid"); reOrderRows($tablename, $ordercol, $swaparray); }


Estoy pensando en este problema, y ​​la solución que encontré es tener un número decimal como orden y cambiar el número del elemento cambiar para un número entre el siguiente y el anterior.

Order Item ----- ---- 1 Original Item 1 2 Original Item 2 3 Original Item 3 4 Original Item 4 5 Original Item 5

Si cambia el elemento 4 a la 2ª posición, obtendrá:

Order Item ----- ---- 1 Original Item 1 1.5 Original Item 4 2 Original Item 2 3 Original Item 3 5 Original Item 5

Si cambia el elemento 3 a la 3ª posición, obtendrá:

Order Item ----- ---- 1 Original Item 1 1.5 Original Item 4 1.75 Original Item 3 2 Original Item 2 5 Original Item 5

Teóricamente, siempre hay un decimal entre dos decimales, pero podría enfrentar algunos límites de almacenamiento.

De esta manera solo tienes que actualizar la fila que se reordena.


La respuesta de soulmerge me hizo pensar y creo que esta es una solución mejor. Lo que debe hacer es seleccionar las filas con el ID usando IN () y luego usar CASE para establecer el valor.

UPDATE mytable SET display_order = CASE id WHEN 10 THEN 1 WHEN 23 THEN 2 WHEN 4 THEN 3 END CASE WHERE id IN (10, 23, 4)

Tengo una necesidad de esto en mi aplicación actual. En PHP, obtengo un conjunto serializado (y ordenado) de identificadores de la función Sortable incorporada de jQuery UI. Así que la matriz se ve así:

$new_order = array(4, 2, 99, 15, 32); // etc

Para generar la única consulta de actualización de MySQL, hago esto:

$query = "UPDATE mytable SET display_order = (CASE id "; foreach($new_order as $sort => $id) { $query .= " WHEN {$id} THEN {$sort}"; } $query .= " END CASE) WHERE id IN (" . implode(",", $new_order) . ")";

El "implode" al final solo me da mi lista de ID para IN (). Esto funciona muy bien para mí.


Podría intentar incluirlo en unas pocas declaraciones, no creo que sea posible en una sola. Así, por ejemplo, digamos que actualizará la décima fila. Quieres que todos los registros después de 10 sean subidos.

UPDATE table SET col=col+1 WHERE col > 10 UPDATE table SET col=10 WHERE id = X ...

Pero es realmente difícil rodar en toda la lógica requerida. Debido a que algunos registros pueden necesitar una disminución, etc. Desea evitar duplicados, etc.

Piense en esto en términos de tiempo de desarrollo contra ganancia.

Porque incluso si alguien ordena esto una vez por día, la sobrecarga es mínima, en comparación con arreglarlo en un procedimiento almacenado, o seudo-optimiza esta función para que no se ejecuten 20 consultas. Si esto no se ejecuta 100 veces al día, 20 consultas están perfectamente bien.


Primero debe asegurarse de que la columna no tenga un índice ÚNICO, de lo contrario mysql le dirá que la restricción se rompió durante la consulta. Después de eso puedes hacer cosas como:

-- Move #10 down (i.e. swap #10 and #11) UPDATE mytable SET display_order = CASE display_order WHEN 10 THEN 11 WHEN 11 THEN 10 END CASE WHERE display_order BETWEEN 10 AND 11; -- Move #4 to #10 UPDATE mytable SET display_order CASE display_order WHEN 4 THEN 10 ELSE display_order - 1 END CASE WHERE display_order BETWEEN 4 AND 10;

Pero realmente debes asegurarte de hacer las cosas en pasos individuales. el intercambio en dos pasos resultará en una numeración rota si no se utilizan identificadores. es decir:

-- Swap in two steps will not work as demostrated here: UPDATE mytable SET display_order = 10 WHERE display_order = 11; -- Now you have two entries with display_order = 10 UPDATE mytable SET display_order = 11 WHERE display_order = 10; -- Now you have two entries with display_order = 11 (both have been changed)

Y aquí hay una referencia a la declaración CASE de mysql .


Puede crear una tabla temporal y rellenar con la clave principal de las filas que desea cambiar, y los nuevos valores de display_order para esas filas, y luego usar la versión de ACTUALIZACIÓN de múltiples tablas para actualizar la tabla de una sola vez. No asumo que esto es más rápido, sin embargo, no sin probar ambos enfoques.


Puede eliminar y volver a insertar todas las filas, lo que haría la operación completa en solo dos consultas (o tres si necesita seleccionar todos los datos). No contaría con que fuera más rápido, y tendría que hacerlo dentro de una transacción o se dirigirá a sus copias de seguridad en poco tiempo. También podría conducir a la fragmentación de la tabla.

Una mejor opción podría ser registrar cada cambio como un historial y luego hacer algo como esto:

Ejemplo, la posición 10 se mueve hacia abajo dos a 12

UPDATE table SET display_order = display_order -1 WHERE display_order BETWEEN 10 AND 12 UPDATE table SET display_order = 12 WHERE row_id = [id of what was row 10]


Recoja el nuevo pedido en una variable temporal y coloque el botón "guardar este pedido" en el área de administración. A continuación, guardar el orden de las filas con una ronda.

Obtendrá mejores tiempos de respuesta, cambios que se pueden deshacer, menos filas modificadas (porque en el nivel bajo de los dbms, prácticamente no se podían realizar actualizaciones, pero guarde una nueva instancia de toda la fila y elimine la anterior).

Después de todo, sería una solución de menor costo para un reordenamiento completo y ahorraría algo de codificación en la optimización de la actualización.


Si necesita arrastrar filas, esta es una buena implementación para una linked list .

Tener sus filas ordenadas con una linked list significa que actualizará a lo sumo 3 filas a la vez, incluso si mueve todo el bloque (siempre que sea contiguo).

Crea una tabla de tus filas como esta:

CREATE TABLE t_list ( id INT NOT NULL PRIMARY KEY, parent INT NOT NULL, value VARCHAR(50) NOT NULL, /* Don''t forget to create an index on PARENT */ KEY ix_list_parent ON (parent) ) id parent value 1 0 Value1 2 3 Value2 3 4 Value3 4 1 Value4

y use esta consulta MySQL para seleccionar las filas en orden:

SELECT @r := ( SELECT id FROM t_list WHERE parent = @r ) AS id FROM ( SELECT @r := 0 ) vars, t_list

Esto atravesará su lista enlazada y devolverá los artículos pedidos:

id parent value 1 0 Value1 4 1 Value4 3 4 Value3 2 3 Value2

Para mover una fila, deberá actualizar el parent de la fila, el parent de su hijo actual y el parent de la fila que está insertando antes.

Vea esta serie de artículos en mi blog sobre cómo hacerlo de manera eficiente en MySQL :

Hay muchos artículos porque hay algunos problemas con el bloqueo de filas que deben manejarse de forma ligeramente diferente para cada caso.


Un poco tarde, pero puede ser útil para otra persona:

UPDATE mytable SET display_order = FIND_IN_SET(rowId, ''1,9,2,6,23'') WHERE rowId in (1,9,2,6,23)