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 :

Déterminer si un update est requis


Sujet :

Requêtes MySQL

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut Déterminer si un update est requis
    Bonsoir,

    je lis un fichier CSV, et pour chaque ligne du fichier, je détermine s'il faut faire un INSERT ou un UPDATE dans la bdd.
    L'une des colonnes du CSV correspond à la clé primaire de la table.
    Donc si la valeur de cette colonne n'existe pas en bdd, INSERT et sinon, si une des autres colonnes a une valeur différente de ce qui se trouve en bdd, UPDATE.
    Voici d'abord la table :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    DROP TABLE IF EXISTS `customer`;
    CREATE TABLE `customer` (
      `customer_login_id` int DEFAULT NULL AUTO_INCREMENT,
      `country_key` smallint DEFAULT NULL,
      `organization` varchar(50) COLLATE utf8_bin DEFAULT NULL,
      PRIMARY KEY (`customer_login_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
    et la seconde table (la première possède une clé étrangère sur la seconde) :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    DROP TABLE IF EXISTS `country`;
    CREATE TABLE `country` (
      `country_key` smallint NOT NULL AUTO_INCREMENT,
      `country` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
      `region` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
      PRIMARY KEY (`country_key`),
      UNIQUE KEY `uk_country` (`country`)
    ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

    Ensuite la requête que j'ai essayée pour savoir s'il fallait faire un UPDATE :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql="SELECT cu.customer_id FROM `customer` AS cu JOIN `country` AS co ON cu.country_key=cu.country_key WHERE ( (co.country!={$ppp($country)} OR cu.organization != {$ppp($organization)} ) AND (`customer_login_ID` = {$ppp($customer_login_id)}) )
    Les {$ppp($xxx)}, ça marche (j'utilise une classe pour exécuter les requêtes). Par contre, la valeur de $customer_login_id n'étant présente qu'une seule fois dans la table customer, j'attends 0 ou 1 résultat. Or j'en obtiens 9 (le nombre d'enregistrements dans la table country qui vérifient la condition co.country!={$ppp($country)}). Peut-on me dire quelle requête j'aurais du faire pour obtenir le résultat escompté ?
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  2. #2
    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 384
    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 384
    Points : 19 088
    Points
    19 088
    Par défaut
    Salut laurentSc.

    Citation Envoyé par laurentSc
    je lis un fichier CSV, et pour chaque ligne du fichier, je détermine s'il faut faire un INSERT ou un UPDATE dans la bdd.
    Tu ne peux pas le faire directement.
    D'abord tu charges ton fichier ".csv" dans une table de travail à partir d'un "load data infile".
    Ensuite, tu réalises la répartition de tes lignes, à partie de la table de travail vers les tables en question, en fonction de tes critères de mise-à-jour.

    Citation Envoyé par laurentSc
    L'une des colonnes du CSV correspond à la clé primaire de la table.
    Je ne vais pas trop me poser de questions sur la fiabilité de cette clef primaire de ton fichier ".csv".
    Disons qu'elle est conforme à ce que tu désires faire.

    Citation Envoyé par laurentSc
    Donc si la valeur de cette colonne n'existe pas en bdd, INSERT et sinon, si une des autres colonnes a une valeur différente de ce qui se trouve en bdd, UPDATE.
    Je ne sais pas si tu le sais, mais il existe une requête mysql qui permet de faire cela.
    Il s'agit de "replace".
    Cela simplifie grandement le traitement car tu ne te poses pas la question si la clef primaire existe déjà ou pas.
    Si la clef primaire existe déjà, ce sera une update, sinon un insert.

    Citation Envoyé par laurentSc
    la première possède une clé étrangère sur la seconde
    Peut-être est-ce la colonne "country_key".
    Ne manquerait-il pas une contrainte de type foreign key dans la table fille par rapport à la table mère ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CONSTRAINT `FK_MERE` FOREIGN KEY (`clef`) REFERENCES `mere` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    Voici ta requête mise d'une manière plus lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT  cu.customer_id
      FROM  `customer` AS cu
      JOIN  `country` AS co
        ON  cu.country_key = cu.country_key
     WHERE  (co.country        != {$ppp($country)}
        OR  cu.organization    != {$ppp($organization)} )
       AND  `customer_login_ID` = {$ppp($customer_login_id)}
    Je ne sais pas si tu as remarqué, mais dans la jointure, tu as mis deux fois "cu.country_key".

    J'ai supprimé la parenthèse global qui n'est pas nécessaire.

    Dois-je comprendre que la clef primaire de ton fichier ".csv" est la colonne cu.customer_id ?

    Citation Envoyé par laurentSc
    Peut-on me dire quelle requête j'aurais dû faire pour obtenir le résultat escompté ?
    Je pense que tu te compliques inutilement en faisant ce genre de test.

    Utilise "replace into `customer` (`customer_id`,`col1`,`col2`) values (val1, val2, val3);".

    Sinon, pour répondre à ta question, je regroupe tes lignes en les comptabilisant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    select           cu.customer_id,
                     count(co.id) as nbre
     
               from  `customer`  as cu
    left outer join  `country` as co
                 on  co.country_key = cu.country_key
     
           group by  cu.customer_id
              WHERE  (co.country        != {$ppp($country)}
                 OR  cu.organization    != {$ppp($organization)} )
                AND  `customer_login_ID` = {$ppp($customer_login_id)};
    Sinon, il existe d'autres solutions avec par exemple le "where exists".

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

  3. #3
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut
    Merci beaucoup pour ta réponse très complète. Tous les points m'intéressent.

    Je vais répondre point par point.

    Tu ne peux pas le faire directement.
    Je suis d'accord, mais j'ai adopté une méthode différente de la tienne : tu proposes de passer par une table de travail (donc une solution SQL). Je fais à peu près la même chose, sauf que c'est une solution PHP. Je stocke d'abord toutes les lignes lues du CSV dans un tableau PHP ; j'analyse la validité des données, puis si pas d'erreur, je fais des INSERT ou des UPDATE.

    Je ne sais pas si tu le sais, mais il existe une requête mysql qui permet de faire cela.
    Je sais ; on peut aussi utiliser insert on duplicate key update, mais mon "client" préfère éviter...

    Ne manquerait-il pas une contrainte de type foreign key dans la table fille par rapport à la table mère ?
    C'est exact. Il en manquait même plusieurs (dans le reste de mon application). Je les ai rajoutées.

    Voici ta requête mise d'une manière plus lisible
    Merci, on m'a déjà fait la correction (j'espère m'en souvenir) :
    Citation Envoyé par escartefigue Voir le message
    Une requête est bien plus facile à lire et donc à comprendre et à maintenir, quand elle est formatée avec soin.

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       SELECT cu.customer_login_id
             , cu.organization
             , co.country 
       FROM `customer` AS cu 
       JOIN `country`  AS co
         ON co.country_key=cu.country_key 
       WHERE co.country='France'
       ;
    Je ne sais pas si tu as remarqué, mais dans la jointure, tu as mis deux fois "cu.country_key".
    Je l'avais remarqué peu après avoir écrit ce post...

    Dois-je comprendre que la clef primaire de ton fichier ".csv" est la colonne cu.customer_id ?
    C'est exact.

    J'en viens à la requête SQL que tu proposes à la fin. J'ai mis des vraies valeurs pour tester :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select           cu.customer_login_id
    from  `customer`  as cu
    left outer join  `country` as co
    on  co.country_key = cu.country_key
     
    group by  cu.customer_login_id,
    WHERE  (co.country        != 'France'
    OR  cu.organization    != 'DE')
    AND  cu.customer_login_ID = 27384;
    J'ai viré une ligne qui semblait être en trop (count(co.id) as nbre). Bien vu le group by pour avoir un seul affichage. Par contre, sur cette requête, il dit qu'il y a une erreur SQL sur la clause WHERE (Si je l'enlève, ça passe). Je ne vois pas
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 142
    Points : 38 926
    Points
    38 926
    Billets dans le blog
    9
    Par défaut
    Bonsoir LaurentSc, bonsoir Artemus24


    @LaurentSc
    Citation Envoyé par laurentSc Voir le message
    Je sais ; on peut aussi utiliser insert on duplicate key update, mais mon "client" préfère éviter...
    Peut être le client envisage-t-il de migrer vers un autre SGBD ? En effet, la syntaxe normative est MERGE et non pas INSERT ON DUPLICATE... qui est une spécificité MySQL/MariaDB.
    En cas de migration, il faut donc réécrire les requêtes concernées


    @Artemus24
    Citation Envoyé par Artemus24 Voir le message
    Voici ta requête mise d'une manière plus lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT  cu.customer_id
      FROM  `customer` AS cu
      JOIN  `country` AS co
        ON  cu.country_key = cu.country_key
     WHERE  (co.country        != {$ppp($country)}
        OR  cu.organization    != {$ppp($organization)} )
       AND  `customer_login_ID` = {$ppp($customer_login_id)
    }
    Ça peut sembler être un point de détail, mais quand des conditions combinent les opérateurs AND et OR, pour éviter toute confusion (les parenthèses étant peu visibles), je préfère indenter pour former des groupes clairs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      FROM  `customer` AS cu
      JOIN  `country` AS co
        ON  cu.country_key = cu.country_key
     WHERE  (     co.country        != {$ppp($country)}
              OR  cu.organization   != {$ppp($organization)} )
       AND  `customer_login_ID`    = {$ppp($customer_login_id)}
    À noter : le prédicat "différent de" n'étant pas "SArgAble", ces critères de recherche sur des tables volumineuses seront très lents (table scan ou index scan oblige)

  5. #5
    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 384
    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 384
    Points : 19 088
    Points
    19 088
    Par défaut
    Bonsoir mon capitaine, bonsoir laurentSc.

    Citation Envoyé par laurentSc
    j'ai adopté une méthode différente de la tienne : tu proposes de passer par une table de travail (donc une solution SQL).
    Je ne vois pas pourquoi, tout faire en mysql serait une mauvaise chose.

    Citation Envoyé par laurentSc
    Je stocke d'abord toutes les lignes lues du CSV dans un tableau PHP ;
    A condition que la volumétrie ne soit pas trop gigantesque.

    Je préfère une solution ensembliste.

    Citation Envoyé par laurentSc
    j'analyse la validité des données, puis si pas d'erreur, je fais des INSERT ou des UPDATE.
    Justement en passant par un table intermédiaire (la table travail), lors de ton chargement, tu peux faire exactement la même chose.
    Il suffit de créer des requêtes qui vont vérifier la validité.
    Si une ligne ne te convient pas, tu peux la stocker dans une autre table du nom poubelle ou recycler.
    Après correction , ou je ne sais quoi d'autre, tu peux à nouveau la réinjecter dans ta table de travail.

    Pour ce qui est des insert et des updates, on peut les éviter.

    Citation Envoyé par laurentSc
    on peut aussi utiliser insert on duplicate key update, mais mon "client" préfère éviter...
    Y-a-t-il un raison à cela ?

    Je trouve bizarre de ne pas utiliser les outils qui sont à notre disposition, et de les réinventer pour faire une usine à gaz.

    Citation Envoyé par laurentSc
    Merci, on m'a déjà fait la correction (j'espère m'en souvenir) :
    Oui, j'ai vu ça dans un autre sujet.

    Citation Envoyé par laurentSc
    Par contre, sur cette requête, il dit qu'il y a une erreur SQL sur la clause WHERE (Si je l'enlève, ça passe). Je ne vois pas
    Voilà ce que c'est de ne pas tester une requête avant de la fournir.
    Il y a un ordre à respecter quand on écrit une requête select.
    Je me fais piéger à chaque fois : il faut mettre le "where" avant le "group by".

    Citation Envoyé par laurentSc
    J'ai viré une ligne qui semblait être en trop (count(co.id) as nbre).
    C'est cette colonne qui va vous servir à dire si vous devez faire un update (nbre > 0) ou un insert (nbre = 0).

    Pour répondre correctement à une question, le mieux est de donner un jeu d'essai complet, représentatif de votre problème.
    Ainsi que la solution que vous désirez obtenir. Sans cela, il est difficile de répondre avec exactitude à votre problème.

    Se focaliser sur un problème fait que l'on n'envisage pas une autre approche.
    Créer un script de chargement, de vérification et d'insertion dans vos tables, le tout en mysql est simple à faire.
    Si vous avez des rejets, ils peuvent être géré par la table poubelle ou recycler et intervenir manuellement pour les résoudre.

    Citation Envoyé par Escartefigue
    En cas de migration, il faut donc réécrire les requêtes concernées
    Migrer, c'est passer d'une logique à une autre. Si la norme est la même des deux cotés, je veux bien.
    Mais il arrive qu'une norme n'a pas été implanté de la même façon dans les deux plates-formes.
    Il est bon de migrer aussi les traitements et pas uniquement les données.

    De même, une requête peut-être performante avant migration et déplorable après.
    Là aussi, il faut revoir les conditions de son fonctionnement.

    Migrer n'est pas aussi simple que de respecter les normes. Il faut tout revoir de fond en comble.

    Citation Envoyé par Escartefigue
    quand des conditions combinent les opérateurs AND et OR pour éviter toute confusion (les parenthèses étant peu visibles), je préfère indenter pour former des groupes clairs :
    Oui, c'est une bonne façon de faire.

    Pour ce qui est de l'opérateur "différent", je préfère utiliser "<>" plutôt que "!=".

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

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 142
    Points : 38 926
    Points
    38 926
    Billets dans le blog
    9
    Par défaut
    Attention concernant ceci :
    Citation Envoyé par laurentSc Voir le message
    Je suis d'accord, mais j'ai adopté une méthode différente de la tienne : tu proposes de passer par une table de travail (donc une solution SQL). Je fais à peu près la même chose, sauf que c'est une solution PHP. Je stocke d'abord toutes les lignes lues du CSV dans un tableau PHP ; j'analyse la validité des données, puis si pas d'erreur, je fais des INSERT ou des UPDATE.
    On un fichier plat type CSV donc non géré par la base de données d'un point de vue transaction. Il faut donc déjà s'assurer de la stabilité de son contenu et de savoir à quel moment il a été produit
    On a par ailleurs une application qui lit ce fichier, le stocke dans une tableau PHP ou une table temporaire, peu importe, et qui sert de base pour déterminer si les identifiants sont nouveaux (auquel cas insert dans la BDD) ou déjà connus (auquel cas update).

    Premier problème :
    Quelle garantie y a-t-il que les données du CSV soient effectivement plus "fraîches" que celles de la BDD ?
    Si une PK présente dans le CSV est trouvée dans la BDD, comment être certain qu'il faut modifier le contenu de la BDD à partir des données du CSV ? A-t-on un horodatage fiable qui permet de s'assurer que les valeurs du fichiers sont plus récentes ?

    Deuxième problème :
    La BDD est rarement dédiée à un seul traitement, si on veut que le fichier pilote les mises à jour de la BDD en fonction de son contenu, il faut interdire tout accès concurrent dès qu'on commence à lire le fichier pour le stocker dans une table PHP ou temporaire ou appliquer directement les modifications. Est-ce bien ainsi que le traitement est conçu ? Si ce n'est pas le cas, les données du fichier CSV peuvent être obsolètes à cause des mises à jour concurrentes.

  7. #7
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut
    Bonjour Artemus24 et escartefigue,

    Citation Envoyé par Artemus24 Voir le message
    Je ne vois pas pourquoi, tout faire en mysql serait une mauvaise chose.
    Je n'ai pas dit que c'était mauvais. Simplement, j'ai actuellement une méthode différente et au point, donc pas très motivé pour en développer une autre...

    Citation Envoyé par Artemus24 Voir le message
    Je préfère une solution ensembliste.
    c'est à dire ?

    Citation Envoyé par Artemus24 Voir le message
    Y-a-t-il un raison à cela ?
    Oui ; je lui ai déjà posé la question mais ai oublié sa réponse (j'oublie beaucoup de choses ). Je lui redemanderai.


    Citation Envoyé par Artemus24 Voir le message
    C'est cette colonne qui va vous servir à dire si vous devez faire un update (nbre > 0) ou un insert (nbre = 0).
    OK et merci. N'ayant pas compris son rôle et comme la PK de country se nomme country_key au lieu de id, j'ai essayé en l'enlevant alors que en effet, elle est très importante et même, j'ai constaté qu'on peut garder uniquement celle-ci (sachant que mon but est juste de déterminer la nécessité d'un update) :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select   count(co.country_key) as nbre
     
               from  `customer`  as cu
    left outer join  `country` as co
                 on  co.country_key = cu.country_key
     
              WHERE  ((co.country        != 'France')
                 OR  (cu.organization    != 'DEDE'))
                AND  (cu.customer_login_id = 27384)
    comme pas besoin de la colonne customer_login_id, du coup, j'ai supprimé le group by. J'ai donc constaté la forte utilité de la colonne nbre mais ne comprends pas le mécanisme. Peux-tu m'expliquer pourquoi on fait select count(co.country_key) ?

    Tu me donnes une solution qui semble convenir, donc je vais d'abord essayer de faire avec et seulement si j'y arrive pas, je donnerai plus de détails...

    escartefigue, j'ai bien vu tes remarques. Réponse courte : mes fichiers CSV sont en fait issus d'un export depuis une autre bdd, donc un contrôle a déjà été effectué. Le but ici est donc de récupérer les données et d'en assurer la lisibilité (l'accès). A priori, un seul utilisateur (et tout le temps le même) utilisera mon application. Donc déjà, pas de risque d'accès concurrent à la bdd (deuxième problème) et avant d'enregistrer les données en bdd, l'idée était de demander une confirmation à l'utilisateur. Donc :
    1- import du fichier CSV.
    2- pour chaque ligne du CSV :
    2-1- analyse de la validité des données
    2-2- si données OK, décision si INSERT ou UPDATE
    2-3- demande de confirmation
    2-4- si oui, commit.
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  8. #8
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut
    artemus24, j'ai utilisé la requête donnée au post #7, et bien qu'un UPDATE soit nécessaire dans le cas testé, ça me retourne 0. Pourquoi ?

    contenu de la table customer:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    INSERT INTO `customer` VALUES 
    (10000,3,'DE'),
    (27000,2,'dede'),
    (27384,1,'DE');

    et pour comprendre les 3 country_key, voici le contenu de la table country :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    INSERT INTO `country` VALUES 
    (1,'France',''),
    (2,'Germany',''),
    (3,'India',''),
    (4,'Sweden',''),
    (5,'Australia',''),
    (6,'United States',''),
    (7,'China',''),
    (8,'Canada',''),
    (9,'Switzerland',''),
    (10,'Austria','');

    Etant donné cela, le triplet testé est (27384,1,'DEDE'). Comme la colonne organization de la table customer a une valeur différente (valeur testée='DEDE' et valeur en BDD pour cet enregistrement='DE'), un UPDATE est requis. Néanmoins, la requête me retourne 0. Comment ça se fait ? (la structure des tables est donnée au post #1)
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  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 384
    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 384
    Points : 19 088
    Points
    19 088
    Par défaut
    Salut LaurentSC.

    Chez moi, ça fonctionne correctement :
    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
    --------------
    START TRANSACTION
    --------------
     
    --------------
    set session collation_connection = "utf8_general_ci"
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE IF NOT EXISTS `base`
            DEFAULT CHARACTER SET `utf8`
            DEFAULT COLLATE       `utf8_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `country`
    --------------
     
    --------------
    CREATE TABLE `country`
    ( `country_key` integer unsigned NOT NULL primary key,
      `country`     varchar(30)      NOT NULL,
      `region`      varchar(30)      NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`utf8` COLLATE=`utf8_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `country` (`country_key`,`country`,`region`) VALUES
    (1,'France',''),
    (2,'Germany',''),
    (3,'India',''),
    (4,'Sweden',''),
    (5,'Australia',''),
    (6,'United States',''),
    (7,'China',''),
    (8,'Canada',''),
    (9,'Switzerland',''),
    (10,'Austria','')
    --------------
     
    --------------
    select * from `country`
    --------------
     
    +-------------+---------------+--------+
    | country_key | country       | region |
    +-------------+---------------+--------+
    |           1 | France        |        |
    |           2 | Germany       |        |
    |           3 | India         |        |
    |           4 | Sweden        |        |
    |           5 | Australia     |        |
    |           6 | United States |        |
    |           7 | China         |        |
    |           8 | Canada        |        |
    |           9 | Switzerland   |        |
    |          10 | Austria       |        |
    +-------------+---------------+--------+
    --------------
    DROP TABLE IF EXISTS `customer`
    --------------
     
    --------------
    CREATE TABLE `customer`
    ( `customer_login_id` integer unsigned NOT NULL primary key,
      `organization`      varchar(30)      NOT NULL,
      `country_key`       integer unsigned NOT NULL,
      CONSTRAINT `FK_COUNTRY` FOREIGN KEY (`country_key`) REFERENCES `country` (`country_key`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`utf8` COLLATE=`utf8_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `customer` (`customer_login_id`,`country_key`,`organization`) VALUES
    (10000,3,'DE'),
    (27000,2,'dede'),
    (27384,1,'DE')
    --------------
     
    --------------
    select * from `customer`
    --------------
     
    +-------------------+--------------+-------------+
    | customer_login_id | organization | country_key |
    +-------------------+--------------+-------------+
    |             10000 | DE           |           3 |
    |             27000 | dede         |           2 |
    |             27384 | DE           |           1 |
    +-------------------+--------------+-------------+
    --------------
    select   count(co.country_key) as nbre
     
               from  `customer`  as cu
     
    left outer join  `country`   as co
                 on  co.country_key = cu.country_key
     
              WHERE  (      (co.country           != 'France')
                        OR  (cu.organization      != 'DEDE')
                     )
                AND          cu.customer_login_id  = 27384
    --------------
     
    +------+
    | nbre |
    +------+
    |    1 |
    +------+
    --------------
    COMMIT
    --------------
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  10. #10
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut
    Je viens seulement de voir ta réponse d'hier...

    J'ai codé cet essai ailleurs, et il marche aussi. J'essaierai plus tard de comprendre pourquoi il ne marche pas, là où j'en ai besoin.

    Par contre, tu ne m'as répondu à ça :
    Citation Envoyé par laurentSc Voir le message
    Je préfère une solution ensembliste.
    c'est à dire ?
    et j'ai posé la question :
    Oui ; je lui ai déjà posé la question mais ai oublié sa réponse (j'oublie beaucoup de choses ). Je lui redemanderai.
    Pour lui, l'algorithme est plus clair (c'est aussi un ancien développeur).
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  11. #11
    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 384
    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 384
    Points : 19 088
    Points
    19 088
    Par défaut
    Salut LaurentSC.

    Citation Envoyé par LaurentSC
    Par contre, tu ne m'as répondu à ça :
    Citation Envoyé par LaurentSC
    Citation Envoyé par Artemus24
    Je préfère une solution ensembliste.
    c'est à dire ?
    Par solution ensembliste, j'entends une solution MySql ou si tu préfères une solution SQL.
    Par opposition à un solution procédurale, c'est-à-dire par php.

    Citation Envoyé par LaurentSC
    Pour lui, l'algorithme est plus clair (c'est aussi un ancien développeur).
    Pourquoi réinventer ce qui existe déjà avec la requête "replace from nom_de_la_table () value ..." ?
    Il serait temps d'évoluer un peu et d'utiliser les outils qui vous simplifie la vie.

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

  12. #12
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 399
    Points : 5 754
    Points
    5 754
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    ça fait plusieurs jours que je ne pouvais travailler sur mon appli mais je viens de m'y remettre.

    J'ai bien noté, Artemus24, que tu aurais fait différemment de moi, mais comme c'est déjà fait et au point, je ne suis pas motivé pour changer mon code.
    Par contre, j'apprécie la requête que tu m'as proposée au post #2. Je l'ai adaptée pour une autre table :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select   count(cu.customer_SESA) as nbre
     
               from  `ticket`  as t
    left outer join  `customer` as cu
                 on  cu.customer_SESA = t.customer_SESA
     
              WHERE  ((cu.organization      != "DE")
                  OR  (t.product_name    != "Phenix"))
              AND  (t.id_ticket = 6425994)
    Comme ça fonctionne, je ne donne pas la structure de ces tables. Mais peux-tu m'expliquer la ligne 1 (pourquoi count(cu.customer_SESA) ?)
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  13. #13
    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 384
    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 384
    Points : 19 088
    Points
    19 088
    Par défaut
    Salut LaurentSC.

    Count() sert à comptabiliser le nombre d'occurrences, c'est-à-dire le nombre de lignes.
    Comme il faut mettre quelque chose entre les parenthèses, le mieux est encore de mettre *.
    S'il n'existe aucune occurrence, tu obtiens zéro.

    --> https://dev.mysql.com/doc/refman/8.0...ting-rows.html

    Tu peux comptabiliser par valeur et non par ligne.
    Si tu mets dans le count(), le nom d'une colonne, tu comptabilises le nombre de lignes où la valeur est différente du marqueur NULL.

    Si tu fais ceci :
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select  count(distinct colonne)
      from  nom_de_ta_table;
    tu comptabilises le nombre distinct de valeurs.
    Ce résultat différera du nombre de lignes.

    Ou bien, tu peux faire aussi :
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      select  colonne, count(*)
        from  nom_de_ta_table
    group by colonne;
    Cette fois-ci, tu comptabiliseras pour chaque valeur le nombre d'occurrences.

    Si tu n'utilises pas le marqueur NULL, tu peux remplacer le "count(cu.customer_SESA)" par "cpount(*)".

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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Déterminer si un champ est une clé primaire
    Par fbalien dans le forum Bases de données
    Réponses: 5
    Dernier message: 23/09/2019, 10h19
  2. [CF][C#]Comment déterminer si mon PPC est bien connecté?
    Par royrremi dans le forum Windows Mobile
    Réponses: 2
    Dernier message: 07/03/2006, 15h35
  3. Déterminer si un nombre est premier
    Par Fandefruit dans le forum Langage
    Réponses: 7
    Dernier message: 30/12/2005, 10h52
  4. Ma requète update est elle conforme ?
    Par CBTech dans le forum Autres SGBD
    Réponses: 2
    Dernier message: 24/05/2005, 21h25
  5. Comment déterminer si un composant est d'un type "TMonT
    Par DanielR dans le forum C++Builder
    Réponses: 2
    Dernier message: 20/03/2004, 18h22

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