Forum Programmation.autre Requete update délicate

Posté par  (site web personnel) .
Étiquettes : aucune
0
28
juil.
2005
bonjour

J'ai bati un MLD que j'héberge sur postgresql et qui est constitué de données venant d'une autre base et de fichiers excel.

Dans une table commande j'ai un champ "activitecmde" que je dois affecter en fonction des valeurs contenues dans client.activitecli.

En gros je dois modéliser la requête :
si commande.activitecmde est < 20 alors, si client.activitecli > 10 where client.numclient = commande.numclient alors commande.activitecmde= client.activitecli

J'ai essayé ça, mais mon statut de débutant en SQL m'a pas permis d'aboutir...


update commande set activitecmde=(select cli.activitecli from client cli, commande c1, affaire a where cli.numclient=a.numclient and c1.numcmde=a.numaffaire) where (select activitecli from client where activitecli>10)


En fait j'aimerai croiser les références de tables entres les différentes sous requêtes de la requête...

Qqun a t-il une idée ?

Merci !
  • # Si j'ai bien compris ta demande...

    Posté par  . Évalué à 2.

    ... tu veux mettre commande.activitecmde a la valeur de client.activitecli si le premier est < 20 et le second > 10 ?

    Tu te compliques la vie (ou alors je n'ai pas compris).

    Reformules ta question :

    Mettre à jour la table commande,
    --> UPDATE commande

    en affectant la valeur de la colonne activitecli de la table client à la colonne activitecmde
    --> SET activitecmde=client.activitecli

    pour toutes les lignes pour lesquelles le numéro de client est le même que celui de la commande
    --> WHERE commande.numclient=client.numclient

    et pour lesquelles l'activitecli est supérieure à 10
    --> AND client.activitecli > 10

    et l'activitecmde est inférieure à 20
    --> AND commande.activitecmde < 20

    Juste ?
    • [^] # Re: Si j'ai bien compris ta demande...

      Posté par  . Évalué à 3.

      Euh... oups, n'importe quoi... Oublie. La table client sort par magie, là... Désolé !
      • [^] # Re: Si j'ai bien compris ta demande...

        Posté par  (site web personnel) . Évalué à 1.

        C'est dommage parce que la requete serait valide... :(

        Sémantiquement parlant

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: Si j'ai bien compris ta demande...

          Posté par  (site web personnel) . Évalué à 1.

          si, si t'avais raison, bravo, il la prend :

          UPDATE commande SET activitecmde=client.activitecli WHERE commande.numcmde=affaire.numaffaire and affaire.numclient=client.numclient AND client.activitecli > 10 AND commande.activitecmde < 20


          > La requête a été exécutée avec succés : 0 lignes modifiées. La requête a été exécutée en 734 ms.


          J'avais pas précisé que numclient est pas ds commande pr simplifier, mais ça revient au même.

          Bon normalement ça va marcher, mais je peux pas vérifier j'ai encore aucune client.activitecli <> 0 (c'est la direction qui le fera, à la mano, au cas par cas....)

          Merci !

          « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

          • [^] # Re: Si j'ai bien compris ta demande...

            Posté par  . Évalué à 2.

            Comment ça il la prend ? On ne lui dit jamais d'utiliser la table client ???
            C'est pas normal là !
            N'utilises pas cette requête !
            Ou alors c'est une syntaxe "avancée" de postgresql...
            Evite.

            Par contre, j'ai trouvé une syntaxe correcte (à adapter avec la table affaire) :

            UPDATE commande
            SET activitecmde = COALESCE(
            ( SELECT activitecli
            FROM client
            WHERE client.numclient = commande.numclient
            AND activitecli > 10
            AND activitecmde < 20
            ), activitecmde);

            Celle là fonctionne.
            En fait, elle met la valeur d'activitecli si elle est trouvée (avec les trois critères). Dans le cas contraire, le sous-requête renvoie NULL, et la fonction COALESCE (dont c'est le rôle - NVL() sous Oracle) renvoie la seconde valeur à la place, soit la valeur originale d'activitecmde, qui sera donc remplacée par elle même...

            Ce n'est pas très propre parceque ça met tout à jour, y compris les lignes qui en réalité ne bougent pas... Ca peut être lourd.
            Je ne voit pas mieux pour l'instant, je ne suis pas vraiment expert en SQL... J'en fait assez peu.

            En fait, un problème comme ça devrait plutôt se régler en deux temps (sélection des lignes concernés, puis mise à jour) avec un curseur ou autre.

            Ma requête va avoir des performances pourries vu qu'on met à jour toute la table...

            Bonne chance.

            Et n'utilise pas ma première requête, ou du moins vérifie avant cette histoire de syntaxe sur la table client non déclarée !
          • [^] # Re: Si j'ai bien compris ta demande...

            Posté par  . Évalué à 2.

            "J'avais pas précisé que numclient est pas ds commande"

            erreur ! c'est un point essentiel !
            Le problème principal de ta requête initiale, c'est que tu ne fais aucun lien entre la ligne de la table commande que tu es en train de mettre à jour et le select de la valeur. Il y a bien la table commande dans les deux cas, mais ton select travaille sur toute la table commande, au lieu de ne travailler que sur la ligne intéressante.

            Il faut que tu explicites le lien entre une commande et un client.
            S'il n'y a pas de numclient dans commande, comment tu lies une commande et un client ? (la table affaire ?)

            Les requêtes d'update un peu complexe, c'est le truc que j'ai mis le plus de temps à intégrer. Pour bien comprendre ce que je fais, je travaille séparément sur les clauses WHERE. La clause WHERE sur la table commande (la seconde ici) sert à limiter le nombre de lignes qu'on va traiter. Ce qu'il faut arriver à se mettre dans le crâne, c'est que quand on travaille sur la clause WHERE dans le SET (la première), on ne travaille plus sur toute la table commande, mais sur une seul des lignes sélectionnée par le WHERE sur la table commande.
            Pour que la valeur qu'on met dans le SET corresponde à quelquechose, il faut absolument faire le lien avec la table commande qu'on update, et pas avec la table commande en général. Un truc du genre

            update commande C -- nommer la table pour pouvoir l'utiliser après
            set activitecmde = (select t.valeur
            from table t
            where T.un_champ = C.un_champ -- la relation entre la table et le select
            ... -- le reste de la clause WHERE)
            where c.activitecmde < 20;

            Pour répondre plus précisément à ta situation, il faut que tu explicites le lien entre une commande et un client.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.