2009-07-20 11 views
4

Je clone et étend l'application Google Tasks. Je veux être en mesure de stocker l'ordre des lignes. J'ai créé un champ dans la base de données, nommé rowNumber. Lorsque l'utilisateur insère une ligne au milieu d'autres, je dois mettre à jour ce champ dans de nombreuses autres lignes pour obtenir la sortie désirée. Il y a une meilleure façon de le faire?Quelle est la meilleure façon de stocker l'ordre entre les lignes de la base de données?

BTW l'application est faite pour le Google App Engine (Python).

+1

Les lignes doivent-elles être incrémentées de un? Que se passe-t-il si vous supprimez une ligne? Recalculez-vous également les lignes restantes? –

+0

Les lignes ne sont pas nécessairement incrémentées de un. Je vois où vous voulez obtenir: si l'incrément est plus élevé, nous pouvons insérer des lignes sans mettre à jour le reste. –

+0

Si vous supprimez une ligne, le reste reste commandé. –

Répondre

3

Définissez rowNumber un nombre à virgule flottante. Lorsque l'utilisateur insère entre les lignes x et y, la nouvelle ligne obtient rowNumber = (x.rowNumber + y.rowNumer)/2.

Lorsque vous voulez déplacer une ligne, simplement mettre à jour son rowNumber de la même manière basé sur la position cible.

Les nouvelles lignes obtiennent rowNumber eg. MAX + 256.

Modifier Microsoft a résolu ce problème dans SQL Server 2008 en utilisant le nouveau type de données HierarchyId. Vous pouvez insérer entre 2 éléments presque autant de fois que vous le souhaitez - jusqu'à ce que vous ayez épuisé la taille maximale HierarchyId.

+0

Beautiful! –

+2

Je ne recommanderais pas d'utiliser un flotteur pour cela. Cela rend simplement plus difficile de prédire le point auquel vous atteignez deux valeurs adjacentes, c'est-à-dire a et b tels que (a + b)/2 soit égal à a, ou à b. Vous devez détecter cette situation et faire quelque chose de spécial. Donc, vous seriez tout aussi bien de commencer avec des entiers à des intervalles de 256 (ou plus) qu'avec des flottants, et il est plus facile avec les entiers d'espacer "uniformément" les valeurs sur toute la plage du type. –

+0

Certes, cette situation peut toujours arriver, par exemple. après 50 insertions à la même position (en utilisant des décimales de haute précision comme rowNumber). J'ai ignoré ça. Utiliser des entiers et recalculer une table entière quand vous atteignez la limite serait mieux. –

3

Une option peut être de stocker des lignes sous la forme d'une liste chaînée, où chaque ligne conserve un champ supplémentaire pour la ligne suivante et précédente. Le côté positif de cela est qu'il ne faut toucher que deux autres rangées après un insert. l'inconvénient est que, (si je comprends bien) AppEngine n'a pas de jointures, donc interroger plus d'une rangée à la fois sera très moche.

+1

Querying serait moche même en SQL, non? –

+0

Et même si interroger cela est possible, il peut ne pas être très rapide, ai-je raison? –

+0

dépend de votre idée de SQL moche. la requête sql sera simplement un groupe de jointures (égal à un de moins que le nombre de lignes que vous souhaitez renvoyer), ce qui équivaut à la suivante d'une rangée au pk de la ligne suivante. La vitesse dépend de la façon dont le SGBD optimise ce type de requête. – SingleNegationElimination

Questions connexes