Usar una columna de orden de clasificación en una tabla de base de datos

Supongamos que tengo una tabla de Product en la base de datos de un sitio de compras para mantener la descripción, el precio, etc. de los productos de la tienda. ¿Cuál es la forma más eficiente de hacer que mi cliente pueda reordenar estos productos?

Creé una columna Order (entero) para usar para ordenar registros, pero eso me da algunos problemas de rendimiento debido a los métodos primitivos que uso para cambiar el orden de cada registro después del que realmente necesito cambiar. Un ejemplo:

 Id Order 5 3 8 1 26 2 32 5 120 4 

Ahora, ¿qué puedo hacer para cambiar el orden del registro con ID=26 a 3?

Lo que hice fue crear un procedimiento que verifica si hay un registro en la orden objective (3) y actualiza el orden de la fila (ID = 26) si no es así. Si hay un registro en el orden de destino, el procedimiento se ejecuta enviando el ID de esa fila con target order + 1 como parámetros.

Eso hace que actualice cada registro individual después del que quiero cambiar para hacer espacio:

 Id Order 5 4 8 1 26 3 32 6 120 5 

Entonces, ¿qué haría una persona más inteligente?

  • Yo uso SQL Server 2008 R2.

Editar:

Necesito que la columna de orden de un artículo sea suficiente para ordenar sin claves secundarias involucradas. La columna Orden solo debe especificar un lugar único para su registro.

Además de todo, me pregunto si puedo implementar algo así como una lista vinculada: una columna ‘Siguiente’ en lugar de una columna ‘Ordenar’ para mantener la siguiente identificación de elementos. Pero no tengo idea de cómo escribir la consulta que recupera los registros con el orden correcto. Si alguien tiene una idea sobre este enfoque también, por favor comparte.

 Update product set order = order+1 where order >= @value changed 

Aunque con el tiempo obtendrás “espacios” cada vez más grandes en tu orden, pero aún así “ordenarán”

Esto agregará 1 al valor que se está cambiando y cada valor después de él en una statement, pero la statement anterior sigue siendo verdadera. Se formarán “espacios” cada vez más grandes en su orden, llegando posiblemente a exceder un valor INT.

Solución alternativa dado el deseo de no espacios:

Imagine un procedimiento para: UpdateSortOrder con parámetros de @NewOrderVal, @ IDToChange, @ OriginalOrderVal

Proceso de dos pasos dependiendo de si el orden nuevo / viejo se mueve hacia arriba o hacia abajo en el orden.

 If @NewOrderVal < @OriginalOrderVal --Moving down chain --Create space for the movement; no point in changing the original Update product set order = order+1 where order BETWEEN @NewOrderVal and @OriginalOrderVal-1; end if If @NewOrderVal > @OriginalOrderVal --Moving up chain --Create space for the momvement; no point in changing the original Update product set order = order-1 where order between @OriginalOrderVal+1 and @NewOrderVal end if --Finally update the one we moved to correct value update product set order = @newOrderVal where ID=@IDToChange; 

En cuanto a las mejores prácticas; la mayoría de los entornos en los que he estado normalmente quieren algo agrupado por categoría y ordenados alfabéticamente o basados ​​en “popularidad en oferta”, lo que anula la necesidad de proporcionar un tipo definido por el usuario.

Utilice el viejo truco que usaron los progtwigs BASIC (entre otros lugares): saltar los números en la columna de orden por 10 o algún otro incremento conveniente. Luego puede insertar una sola fila (de hecho, hasta 9 filas, si tiene suerte) entre dos números existentes (que son 10 separados). O puede mover la fila 370 a la 565 sin tener que cambiar ninguna de las filas de 570 hacia arriba.

Una solución que he utilizado en el pasado, con cierto éxito, es usar un ‘peso’ en lugar de ‘orden’. El peso es lo obvio, el elemento más pesado (es decir, cuanto menor es el número) se hunde hacia el fondo, mientras más ligero (más alto es el número) se eleva a la parte superior.

En caso de que tenga varios elementos con el mismo peso, supongo que son de la misma importancia y los ordeno alfabéticamente.

Esto significa que su SQL se verá más o menos así:

 ORDER BY 'weight', 'itemName' 

Espero que ayude.

Aquí hay un enfoque alternativo usando una expresión de tabla común (CTE).

Este enfoque respeta un índice único en la columna SortOrder y cerrará cualquier hueco en la secuencia de orden que pueda haber quedado de las operaciones DELETE anteriores.

 /* For example, move Product with id = 26 into position 3 */ DECLARE @id int = 26 DECLARE @sortOrder int = 3 ;WITH Sorted AS ( SELECT Id, ROW_NUMBER() OVER (ORDER BY SortOrder) AS RowNumber FROM Product WHERE Id <> @id ) UPDATE p SET p.SortOrder = (CASE WHEN p.Id = @id THEN @sortOrder WHEN s.RowNumber >= @sortOrder THEN s.RowNumber + 1 ELSE s.RowNumber END) FROM Product p LEFT JOIN Sorted s ON p.Id = s.Id 

Actualmente estoy desarrollando una base de datos con una estructura de árbol que necesita ordenarse. Utilizo un tipo de método de lista de enlaces que se ordenará en el cliente (no en la base de datos). El pedido también se puede hacer en la base de datos a través de una consulta recursiva, pero eso no es necesario para este proyecto.

Hice este documento que describe cómo vamos a implementar el almacenamiento del orden de clasificación, incluido un ejemplo en postgresql. Por favor, siéntete libre de comentar!

https://docs.google.com/document/d/14WuVyGk6ffYyrTzuypY38aIXZIs8H-HbA81st-syFFI/edit?usp=sharing

(perdón por el inglés, estoy estudiando)

Es muy simple. Necesitas tener un “agujero de cardinalidad”

estructura que necesita para tener 2 columnas

1) pk = 32bit int

2) orden = 64 bits bigint (BIGINT, NO DOBLE !!!)

insertar / actualizar

1) cuando insertas el primer registro nuevo debes establecer order = round (max_bigint / 2).

2) si inserta al comienzo de la tabla, debe establecer order = round (“orden del primer registro” / 2)

3) si inserta al final de la tabla, debe establecer order = round (“max_bigint – orden del último registro” / 2)

4) si inserta en el centro, debe establecer order = round (“orden de registro anterior – orden del registro después de” / 2)

este método tiene un gran cariño. si tiene un error de restricción o si cree que tiene una cardinalidad pequeña, puede reconstruir la columna de orden (normalizar).

en la situación de máxima con normalización (con esta estructura) puede tener un “agujero de cardinalidad” en 32 bits.

es muy simple y rápido!

recuerda NO HAY DOBLE !!! ¡Sólo INT – orden es el valor de precisión!