10
votes

Quelle serait la meilleure façon de stocker l'ordre des enregistrements dans SQL

J'ai une table des profils d'utilisateurs. Chaque utilisateur peut avoir de nombreux profils et l'utilisateur a la possibilité d'arbriquer l'ordre de la manière dont ils seront affichés dans une grille.

Il existe 2 tables utilisateurs et profils (1: M)

J'ai ajouté une colonne Colonne sur la table des utilisateurs où seront des valeurs telles que 1,2,3 ..

Jusqu'à présent, cela semble être correct. Mais lorsqu'un utilisateur changera l'ordre du dernier enregistrement pour être le premier, je dois passer à tous les enregistrements et incrémenter leurs valeurs +1. Cela me semble assez moche.

Y a-t-il une solution plus pratique pour ce type de situation?

sql

0 commentaires

7 Réponses :


10
votes

laisser des lacunes dans la séquence ou utiliser une décimale plutôt qu'un type de données entier.


1 commentaires

Utilisez des chaînes (Varchar, texte). Les chaînes ont implicitement une "précision arbitraire" indéfinie. Stackoverflow.com/a/49956113/10608



2
votes

En tant qu'utilisateur ajoute des profils, définissez chaque nouveau numéro de commande du nouveau profil sur le précédent +1000000. par exemple. Pour commencer avec: xxx

Lors de la réorganisation, définissez la commande du profil au milieu des deux, il se passe entre: xxx

Cela donne à la commande P1, P3, P2


0 commentaires

4
votes

Que diriez-vous d'utiliser des points flottants pour la commande par colonne? De cette façon, vous pouvez toujours presser un profil entre deux autres, sans avoir à changer ces deux valeurs. Par exemple, si je veux placer le profil A entre profils B (ordervalue 1) et c (ordervalue 2), je peux affecter la commandevalue 1.5 à A. Pour le placer sur le dessus, où avant le sommet utilisé pour avoir OrderValue, vous pouvez utiliser OrderValue 0.5

Il n'y a aucune raison d'avoir des entiers pour commander et aucune raison d'avoir des incréments de 1 entre l'ordre des profils.


1 commentaires

Disons que vous avez 3 enregistrements, vous attribuez des numéros 1,2,3 pour eux. Ensuite, vous réorganisez une dernière pour être entre deux premiers et obtenir 1,5 numéro pour cela. Ensuite, répétez le processus et chaque fois que vous le ferez plus près de 1, comme 1,25, 1,125, etc. Jusqu'à ce que vous atteigniez la limite de précision, cela vient très bientôt, 50 itérations. Ensuite, vous avez des bugs méchants ... :(



1
votes

Je pense que l'idée de laisser des lacunes entre les commandes est intéressante, mais je ne sais pas si c'est une solution "plus pratique" pour votre problème.

Je pense que vous feriez mieux de mettre à jour votre par colonne. Parce que vous allez toujours devoir déterminer les lignes déplacées entre les états et sur quoi faire si deux statuts sont commutés en position (calculez-vous la nouvelle commande par valeur pour le premier puis le second). Que se passe-t-il si l'écart entre n'est pas assez grand?

Cela ne devrait pas être que les données intensives pour énumérer l'ordre dans lequel ils l'ont mis et mettent à jour chaque enregistrement à la commande.


0 commentaires

4
votes

La meilleure solution est une solution qui miroirs fonctionnalité , et c'est une liste simple d'entiers. Garder la liste dans l'ordre n'est que quelques déclarations SQL, et plus facile à comprendre que les autres solutions suggérées (flotteurs, entiers gappés).

Si vos listes étaient très volumineuses (dans les dizaines de milliers), les considérations de performance peuvent entrer en jeu, mais je suppose que ces listes ne sont pas aussi longues.


1 commentaires

+1 Lorsque la sémantique du problème correspond à celle de la solution, il y a moins d'endroits pour se cacher.



3
votes

Si le jeu de données est petit (ce qui semble être le cas), je préférerais utiliser une liste normale d'entiers et les mettre à jour en lot lorsqu'un profil obtient une nouvelle position. Cela reflète mieux la fonctionnalité de l'application.

dans SQL Server, pour le tableau suivant user_profiles (user_id, profil_id, position) code>, j'aurais quelque chose comme ceci: P>

--# 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 commentaires

2
votes

Je pense au lieu de garder l'ordre dans la colonne OrderBy Vous pouvez introduire le concept de liste de liaison à votre conception. Ajouter une colonne comme NextID qui contiendra le profil suivant de la chaîne. Lorsque vous interrogez la table , vous pouvez trier les profils de votre code (Java, C #, etc.)


0 commentaires