2010-09-28 11 views
7

Tengo una tabla de perfiles de usuarios. Cada usuario puede tener muchos perfiles y el usuario tiene la capacidad de ordenar el orden de cómo se mostrarán en una cuadrícula.Cuál sería la mejor forma de almacenar registros en SQL

Hay 2 mesas de usuarios y perfiles (1: M)

He añadido una columna orderby a la mesa donde los usuarios serán valores como 1,2,3 ..

Hasta el momento parece estar bien Pero cuando un usuario cambiará el orden del último registro para ser el primero, tengo que pasar por todos los registros e incrementar sus valores +1. Esto me parece bastante feo.

¿Hay alguna solución más conveniente para este tipo de situación?

Respuesta

3

La mejor solución es aquella que duplica la funcionalidad, y esa es una simple lista de enteros. Mantener la lista en orden es solo unas pocas declaraciones SQL, y más fácil de entender que las otras soluciones sugeridas (flotantes, enteros vacíos).

Si sus listas eran muy grandes (en decenas de miles), entonces las consideraciones de rendimiento podrían entrar en juego, pero supongo que estas listas no son tan largas.

+0

+1 Cuando la semántica del problema coincide con la de la solución, hay menos lugares para que los errores se oculten. –

8

Deje huecos en la secuencia o use un tipo de datos decimal en lugar de enteros.

+2

Preferiblemente el segundo. –

1

Como un usuario agrega perfiles, establezca el número de pedido de cada perfil nuevo en el anterior +1000000. p.ej. para empezar con:

p1 1000000 
p2 2000000 
p3 3000000 

Cuando la reordenación, establece la orden del perfil a la media de los dos que va en el medio:

p1 1000000 
p2 2000000 
p3 1500000 

Esto da p1 orden, P3, P2

3

¿Qué le parece usar puntos flotantes para el orden por columna? De esta manera, siempre puede exprimir un perfil entre otros dos, sin tener que cambiar esos dos valores. Por ejemplo, si quiero colocar el perfil A entre los perfiles B (valor de pedido 1) y C (valor de pedido 2), puedo asignar el valor de orden 1.5 a A. Para colocarlo en la parte superior, donde antes solía tener un valor de orden de 1, usted puede usar ordervalue 0.5

No hay razón para tener enteros para el pedido y no hay razón para tener incrementos de 1 entre el orden de los perfiles.

+0

+1 - Batirme a eso. – JNK

+4

Digamos que tiene 3 registros, asigne los números 1,2,3 para ellos. Luego reordenas el último para que esté entre los primeros dos, y obtienes un número 1.5 para él. Luego repite el proceso, y cada vez lo acercarás a 1, como 1.25, 1.125, etc. HASTA GOLPEA EL LÍMITE DE PRECISIÓN, y esto llega muy pronto, 50 iteraciones. Entonces tiene un desagradable error ... :( – Hrissan

1

Creo que la idea de dejar huecos entre los pedidos es interesante, pero no sé si es una solución "más conveniente" para su problema.

Creo que sería mejor que simplemente actualizando su columna order by. Porque todavía tendrá que determinar en qué filas se han movido los estados, y qué hacer si dos estados se cambian de posición (¿Calcula el nuevo orden por valor para el primero y luego para el segundo). ¿Qué sucede si la brecha entre ellos no es lo suficientemente grande?

No debería ser tan intenso el uso de datos para simplemente enumerar el orden en que lo colocaron y actualizar cada registro en el orden.

2

Si el conjunto de datos es pequeño (lo que parece ser el caso), preferiría utilizar una lista normal de enteros y actualizarlos en lote cuando un perfil obtiene una nueva posición.Esto refleja mejor la funcionalidad de la aplicación.

en SQL Server, para la tabla User_Profiles (user_id, profile_id, position) siguiente, tendría algo como esto:

--# The variables are: 
--# @user_id - id of the user 
--# @profile_id - id of the profile to change 
--# @new_position - new position that the profile will take 
--# @old_position - current position of the profile 

select @old_position = position 
from User_Profiles where 
user_id = @user_id and profile_id = @profile_id 

update p set position = pp.new_position 
from User_Profiles p join (
    select user_id, profile_id, 
    case 
    when position = @old_position then @new_position 
    when @new_position > @old_position then --# move up 
     case 
     when @old_position < position and 
      position <= @new_position 
     then position - 1 
     else position 
     end 
    when @new_position < @old_position then --# move down 
     case 
     when position < @old_position and 
      @new_position <= position 
     then position + 1 
     else position 
     end 
    else position --# the same 
    end as new_position 
    from User_Profiles p where user_id = @user_id 
) as pp on 
p.user_id = pp.user_id and p.profile_id = pp.profile_id 
0

Creo que en lugar de mantener el orden en la columna orderby se puede introducir el concepto linklist a su diseño. Agregue una columna como nextId que contendrá el siguiente perfil de la cadena. Cuando consulta la tabla profiles puede ordenar perfiles en su código (java, C#, etc.)

Cuestiones relacionadas