IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Update d'une colonne ordre


Sujet :

Requêtes MySQL

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut Update d'une colonne ordre
    Bonjour à tous,

    Dans le cadre de mon activité, on me demande de pouvoir ordonner une table sur base d'une colonne ordre, j'ai donc un tableau HTML dans la zone admin, avec une colonne "+ ordre -".
    En cliquant sur le petit plus on monte la valeur de ordre, et inversement avec le moins.

    Dés lors comment impacté toute la table de manière à ne pas avoir de doublon dans l'ordre.
    Si une position est en passée en de 2 à 3, il faut que 2 deviennent 3, pas de soucis, mais admettons que de 3 je le passe à 8 comment impacté tous les ordonnées pour gardé une cohérence.

    Je ne sait pas si vous voyer ce que je veux dire

    Pour l'instant ma requête est très simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    UPDATE ma_table SET ordre=ordre+1 (ou -1) WHERE id=MONID;
    Mais je ne vois pas comment régler le problème de doublon dans l'ordre, et je ne veux pas me retrouver avec par exemple 6 ligne ordonnées en position 8 ni avec des trous
    Cela signifie je suppose aussi que lors de l' insertion/suppression il faut réordonner la table

    En vous remerciant d'avance pour votre contribution
    Bien à vous
    Spliffer

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 801
    Points
    30 801
    Par défaut
    S'il s'agit juste d'inverser une ligne et sa suivante (ou précédennte), il suffit de faire précéder ta requête de celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    UPDATE  ma_table
    SET     ordre = ordre - 1 (ou + 1) 
    WHERE   ordre   IN
            (   SELECT  ordre + 1 (ou - 1)
                FROM    ma_table
                WHERE   id = MONID
            )
    ;
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    Bonjour, tout d'abord merci pour votre participation.

    Voici ce que j'ai fait c'est mit dans du PHP mais c'est bien la requête SQL dont on parle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // Si dir = 0 : on doit descendre de 1 et corriger en conséquence les précédents et suivants
    // Si dir = 1 : on doit monter de 1 et corriger en conséquence les suivants et précédents
    if($dir == 0){
        $req = "UPDATE  ma_table SET ordre = ordre - 1 WHERE ordre IN 
                 ( SELECT ordre + 1 FROM ma_table WHERE id = ".$id." );";
    }
    else{
        $req = "UPDATE  ma_table SET ordre = ordre + 1 WHERE ordre IN 
                 ( SELECT ordre - 1 FROM ma_table WHERE id = ".$id." );";
    }
    et j'obtiens un message d'erreur que voici :
    You can't specify target table 'ma_table' for update in FROM clause
    Je regarde mais je ne comprend pas cette erreur, traduit littéralement ça donnerai quelques choses du genre :
    Vous ne pouvez pas spécifier la table cible 'ma_table' pour la mise à jour dans la clause FROM
    Du coup je vois pas comment corriger, car si je ne cible pas 'ma_table' comment peut-il comprendre la sous-requête ? (sous-requête est-ce le bon mot ?)

    Bien à vous
    Splifffer

  4. #4
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 801
    Points
    30 801
    Par défaut
    Les joies des limitations de MySQL
    Ma réponse la plus sensée : changez de SGBD ! Les vrais savent faire cette opération.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    Lol, mais je n'ai pas le choix, MySQL m'est imposé, les joie de travailler pour un patron têtu

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    bonjour,

    Citation Envoyé par splifferwolf Voir le message
    admettons que de 3 je le passe à 8 comment impacté tous les ordonnées pour gardé une cohérence.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    UPDATE LaTable
        SET ordre = CASE WHEN ordre = 3 THEN 8 ELSE ordre - 1 END
    WHERE ordre BETWEEN 3 AND 8

  7. #7
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    Bonsoir et merci de votre participation,

    C'est nickel, ça fonctionne parfaitement ou presque.
    Je doit faire une erreur quelques part car ça fonctionne si je modifie la position de 1 place, si je veux mettre directement le 8 en 3 par exemple sans passer par 5 click sur le + ca ne change rien, il me le modifie toujours de 1.
    Je me suis dit que ca devait être l'opérante le problème, j'ai donc modifie le -1 par "-".$nb ou "+".$nb, mais évidement il me les descend tous de x ou monte de x
    Ainsi certes le 8 se transforme en 3 mais le 1 se transforme en -4 (logique 1-5 = -4), le 2 devient -3, etc...

    Enfin voilà, je sais pas si je suis très clair dans mes explications, c'est pourquoi je vous met ma source, je me dit qu'il doit y avoir moyen mais je patauge un peu, donc pour l'instant je laisse juste la possibilité de modifier de 1 uniquement et je cherche encore à résoudre la fin du problème.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
        // Id de l'élément c'était au cas ou
        $id = (isset($_POST['ide'])) ? $_POST['ide'] : 0;
     
        // Sens +(1) ou -(0)
        $dir = (isset($_POST['dir']) && $_POST['dir'] == 1) ? 1 : 0;
     
        // L'ordre actuel (qui donne le départ logiquement), Sinon 0 (soit le premier à l'affichage)
        $ordreActual = (isset($_POST['ordre'])) ? $_POST['ordre'] : 0;
     
        // La nouvel position souhaitée (on monte ou descend de x position), j'utilise la fonction qui retourne l'absolue (sans le -), si je met le 8 en 3 $nb = 5
        $nb = (isset($_POST['nb']) && $_POST['nb'] > 0) ? abs($_POST['nb']) : 1;
     
        // Le prochain ordre en fonction de si on monte ou on descend
        $ordreNext = ($dir == 1) ? $ordreActual-$nb : $ordreActual+$nb;
     
        // On empêche de monter en nombre négatif (je veux pas de -1, -2 etc...)    
        $ordreNext = ($ordreNext < 0) ? 0 : $ordreNext;
     
        // Opérante, on doit faire +1 ou -1
        $operante = ($dir == 1) ? "-1" : "+1";
     
        // Définit le départ
        $start = ($ordreActual < $ordreNext) ? $ordreActual : $ordreNext;
     
        // Définit la fin
        $end = ($ordreActual < $ordreNext ) ? $ordreNext : $ordreActual;
     
        // La requête,
        $req = "UPDATE ma_table
                SET ordre = CASE WHEN ordre = ".$start." THEN ".$end." ELSE ordre ".$operante." END
                WHERE ordre BETWEEN ".$start." AND ".$end;
     
        // On exécute la requête
        $qry = $pdo->query($req);

    D'avance merci
    Bien à vous

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Déjà, je pense qu'il ya une inversion à ce niveau :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Opérante, on doit faire +1 ou -1
        $operante = ($dir == 1) ? "-1" : "+1";
    à vérifier...


    Ensuite, il faut gérer deux cas dans la requête, en fonction du sens.
    Au niveau du BETWEEN, il faut toujours que la borne inférieure soit en premier, et la borne supérieure en deuxième.

    En revanche, au niveau du CASE, il faut toujours mettre la position initiale dans le test, et la position finale dans le THENLe mieux serait de faire afficher votre requête SQL, vous comprendriez mieux l'erreur.

    Je pense qu'il suffirait dans votre requête de remplacer $start par $OrdreActual et $end par $OrdreNext, mais uniquement dans le CASE

  9. #9
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut splifferwolf.

    D'après ce que j'au pu comprendre, vous désirez modifier une colonne en lui ajoutant un incrément de façon à ne pas obtenir une erreur du type doublon.

    Quel est l'intérêt de procéder ainsi ?


    Voici quelques exemples de modifications de la colonne "ordre" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
        DEFAULT CHARACTER SET `latin1`
        DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    ( `id`      integer unsigned  not null auto_increment primary key,
      `ordre`   integer unsigned  not null
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `test` (`ordre`) values
      (11),(15),(17),(25),(33),(37),(41),(45),(49)
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | ordre |
    +----+-------+
    |  1 |    11 |
    |  2 |    15 |
    |  3 |    17 |
    |  4 |    25 |
    |  5 |    33 |
    |  6 |    37 |
    |  7 |    41 |
    |  8 |    45 |
    |  9 |    49 |
    +----+-------+
    --------------
    commit
    --------------
     
    --------------
    update    `test`
         set  ordre = ordre + 1
    order by  ordre
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | ordre |
    +----+-------+
    |  1 |    12 |
    |  2 |    16 |
    |  3 |    18 |
    |  4 |    26 |
    |  5 |    34 |
    |  6 |    38 |
    |  7 |    42 |
    |  8 |    46 |
    |  9 |    50 |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    update    `test`
         set  ordre = ordre - 8
    order by  ordre
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | ordre |
    +----+-------+
    |  1 |     3 |
    |  2 |     7 |
    |  3 |     9 |
    |  4 |    17 |
    |  5 |    25 |
    |  6 |    29 |
    |  7 |    33 |
    |  8 |    37 |
    |  9 |    41 |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    set @rang = 8
    --------------
     
    --------------
    update    `test`
         set  ordre = (@rang:=@rang + 1)
    order by  id
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | ordre |
    +----+-------+
    |  1 |     9 |
    |  2 |    10 |
    |  3 |    11 |
    |  4 |    12 |
    |  5 |    13 |
    |  6 |    14 |
    |  7 |    15 |
    |  8 |    16 |
    |  9 |    17 |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    set @rang = 20
    --------------
     
    --------------
    update    `test`
         set  ordre = (@rang:=@rang - 2)
    order by  id
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+-------+
    | id | ordre |
    +----+-------+
    |  1 |    18 |
    |  2 |    16 |
    |  3 |    14 |
    |  4 |    12 |
    |  5 |    10 |
    |  6 |     8 |
    |  7 |     6 |
    |  8 |     4 |
    |  9 |     2 |
    +----+-------+
    --------------
    rollback
    --------------
     
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
    Appuyez sur une touche pour continuer...
    Citation Envoyé par splifferwolf
    Je ne sais pas si vous voyer ce que je veux dire
    Pas très bien, car le mieux serait de nous donner un jeu d'essai avec un exemple de ce que vous désirez obtenir.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/06/2007, 16h05
  2. update d'une colonne entière sous bde
    Par gregcat dans le forum Bases de données
    Réponses: 1
    Dernier message: 23/03/2007, 21h46
  3. [MySQL] Trier les résultats en fonction d'une colonne ordre
    Par eclipse012 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 05/01/2007, 13h59
  4. Réponses: 4
    Dernier message: 31/10/2006, 19h03
  5. update d'une colonne texte
    Par todd dans le forum Requêtes
    Réponses: 2
    Dernier message: 02/10/2003, 13h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo