Question

J'ai une table d'enregistrements dans mySql. J'ai besoin de maintenir une commande pour eux comme spécifié par l'utilisateur. J'ai donc ajouté une colonne "position".

Quelle serait l'instruction SQL pour mettre à jour tous les enregistrements lorsque je déplace un enregistrement spécifique? J'ai quelque chose comme:

UPDATE items SET position = '2' WHERE id ='4';
UPDATE items SET position = position+1 WHERE position >= '2' AND id != '4';

Mais le plus grand que va être un moins que si l'enregistrement a baissé. C'est quoi le truc? Merci!

Était-ce utile?

La solution

Faire ce genre de chose, par exemple les commandes avec des numéros de ligne gérés par l'utilisateur, je trouve qu'il est préférable de le gérer dans un tableau dans le BL ou l'interface utilisateur. Habituellement, ils voudront ajuster plusieurs enregistrements et parfois vouloir dire & "Oublie ça &"; Donc, le plus simple serait peut-être d’attendre qu’ils atteignent le & «OK &»; (ou votre équivalent), puis réécrivez-les tous avec la commande en cours.

Vous pouvez également vous retrouver avec des suppressions, ce qui est un autre problème que vous pouvez gérer de la même façon.

Autres conseils

Quelque chose comme ça le ferait-il?

UPDATE items 
SET position = CASE position 
  WHEN $oldpos THEN $newpos 
  ELSE position + SIGN($oldpos-$newpos)
 END
WHERE position BETWEEN LEAST( $newpos, $oldpos ) 
                AND GREATEST( $newpos, $oldpos );

Je l'ai testé à quelques reprises et cela semble fonctionner.

Voici ce que je pense de ceci: ma colonne row_index a un numéro avec un pas de 10 (par exemple: 0, 10, 20, etc.). Lorsqu'un utilisateur met à jour une des lignes, vous devez savoir si elle va vers le haut ou vers le bas. Si vous devez déplacer la 2e ligne vers la 4e (en descendant, row_index souhaité = 30), vous définissez row_index sur 35; sinon (si vous montez), réglez-le sur 25. Définissez cette valeur:

UPDATE your_table SET row_index = 35 WHERE your_id = 1234

Maintenant, vous avez le bon ordre, mais les index_lignes sont altérés. Pour résoudre ce problème, exécutez ces deux requêtes:

SET @pos:=-10;
UPDATE your_table SET row_index = @pos:=@pos+10 WHERE ...

Ceci va mettre à jour toutes vos lignes (ou celle que vous avez sélectionnée avec l'instruction where) et définir la colonne row_index sans espaces (0, 10, 20, 30, etc.). De cette manière, les opérations d’écriture sont surchargées, mais je pense que c’est le moyen le plus rapide d’obtenir l’ordre lors des opérations de lecture. Si vous supprimez une ligne, vous pouvez simplement réexécuter les requêtes d’ordre de résolution.

Je suggérerais, au minimum, d’utiliser des incréments importants (par exemple 10 000) entre les éléments. Puis je fais juste une commande par. Si vous devez déplacer 11 000 entre 9 000 et 10 000, réglez-le simplement sur 9500 et c'est tout.

Cela n’élimine pas le problème de la réorganisation mais le réduit considérablement. À un moment donné, vous feriez mieux de supprimer toutes les lignes, puis de les lire dans le bon ordre. Faire des mises à jour comme vous le faites est tout simplement trop sujet aux erreurs.

Vous pouvez envisager d'utiliser une approche de type liste chaînée, avec une clé pour le suivant et peut-être l'élément précédent de la liste. Il vous suffira alors de mettre à jour quelques enregistrements au lieu de tous.

Intéressant! Ok, donc il n'y a pas de réponse facile. Je pensais qu'il me manquait quelque chose. J'avais pensé à maintenir un tableau externe. Cela semble être la meilleure idée.

Peut-être quelque chose comme ça?

$item_id = $_GET['item_id']; 
$position = $_GET['new_position']; 
$old_position = $_GET['old_position'];

if($new_position < $old_position) {
    SQL: UPDATE items SET position = position+1 WHERE position >= $new_position AND position < $old_position  
} else {  
SQL: UPDATE items SET position = position-1 WHERE position <= $new_position AND position > $old_position
}  

SQL: UPDATE items SET position = $new_position WHERE item_id = $item_id 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top