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

MS SQL Server Discussion :

Update avec un select


Sujet :

MS SQL Server

  1. #1
    Membre à l'essai
    Femme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juillet 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2012
    Messages : 13
    Points : 11
    Points
    11
    Par défaut Update avec un select
    Bonjour,

    Je viens depuis la semaine derniere de recuperer un nouveau projet et je bloque sur une requete . J'ai beau la tourner dans tous les sens .... ca veut pas.

    J'ai une table INTERVENTION qui contient les interventions realisees sur des vehicules (poids lourd).Elle contient un champ IDIMMAT qui est lié avec la table VEHICULE qui contient les vehicules avec une MARQUE.
    Le champ IDMARQUE est lié avec la table des VEHICULEMARQUE.

    Pour récapituler:

    Table INTERVENTION   : IDINTERVENTION, IDIMMAT
    Table VEHICULE       : IDIMMAT       , IDMARQUE
    Table VEHICULEMARQUE : IDMARQUE      , INTNBREINTERVENTION

    Je ne sais pas pourquoi mais le concepteur souhaite que dans la table VehiculeMarque soit stocké le nombre d'intervention par marque (je lui ai expliquée que je ne vois pas l'utilitée ..... bref !) au travers du champ IntNbreIntervention


    Comment donc mettre a jour cette information.

    J'ai tenté un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE VehiculeMarque
       SET IntNbreIntervention = (select count(*)
                                    from Intervention
                                    join ......
                                      on vehiculemarque.IDMarque = TableJointe.IDMarque);
    cela ne fonctionne ppaaasssss.

    Une idée ?

    Merci d'avance pour vos réponses et votre lecture.
    Passez de bonnes fêtes.

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut Vous avez dit : update déterministe ?
    Bonsoir pompom75,


    Histoire d’y voir plus clair, j’utilise une CTE (Common Table Expression) pour la partie SELECT. Pour la partie UPDATE, il s’agit d’une technique propre à MS SQL Server, mais attention ! Cette technique n’est pas conforme à la norme SQL et en plus elle n’est pas déterministe (horresco referens !) J’espère que vos tables sont dotées de clés, sinon ça craint...

    Je cherche simplement ici à vous dépanner provisoirement, mais je ne doute pas que nos champions du SQL, les Waldar, SQLpro, Mikedavem, iberserk, elsuket, pour ne citer qu’eux, sauront traiter votre problème de façon élégante et conforme à la norme, et au besoin corriger la requête que je propose.

    Un exemple

    Les tables que j’utilise :

    Code SQL : 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
    CREATE TABLE MARQUE
    (
            IdMarque          INT          NOT NULL
          , NbInterv          INT          NOT NULL DEFAULT 0
        , CONSTRAINT MARQUE_PK PRIMARY KEY (IdMarque) 
    ) ;
     
    CREATE TABLE VEHICULE
    (
            IdVehicule        INT          NOT NULL
          , IdMarque          INT          NOT NULL
        , CONSTRAINT VEHICULE_PK PRIMARY KEY (IdVehicule) 
        , CONSTRAINT VEHICULE_FK FOREIGN KEY (IdMarque) REFERENCES MARQUE
    ) ;
     
    CREATE TABLE INTERVENTION
    (
            IdInterv          INT          NOT NULL
          , IdVehicule        INT          NOT NULL
        , CONSTRAINT INTERVENTION_PK PRIMARY KEY (IdInterv) 
        , CONSTRAINT INTERVENTION_FK FOREIGN KEY (IdVehicule) REFERENCES VEHICULE
    ) ;

    La requête de mise à jour :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ;
    WITH Comptage (IdMarque, kount)
    AS 
    (
     SELECT z.IdMarque, COUNT(*) AS kount
     FROM   INTERVENTION AS x JOIN VEHICULE AS y ON x.IdVehicule = y.IdVehicule
               JOIN MARQUE AS z ON y.IdMarque = z.IdMarque
     GROUP BY z.IdMarque
    )
    UPDATE MARQUE 
        SET NbInterv = kount
        FROM MARQUE AS x JOIN Comptage AS y ON x.IdMarque = y.IdMarque ;

    Et Bonne année à tous !

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 394
    Points
    18 394
    Par défaut
    Il faudrait voir votre requête complète, il n'y a pas de raison que ce que vous avez écrit ne fonctionne pas.

    Pour votre problème, il faut mettre un trigger sur votre table intervention qui va ajouter 1 à la colonne NbIntervention de la table VehiculeMarque sur une insertion de ligne ou retirer 1 si c'est une suppression.

  4. #4
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonsoir pompom75,


    Citation Envoyé par pompom75 Voir le message
    J'ai tenté un :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE VehiculeMarque
       SET IntNbreIntervention = (select count(*)
                                    from Intervention
                                    join ......
                                      on vehiculemarque.IDMarque = TableJointe.IDMarque);
    En fait le SELECT produit autant de valeurs de COUNT(*) que de marques, alors que légalement on n'a droit qu'à une seule valeur pour l'update.

    Pour éviter une infraction à la norme SQL, on peut remplacer ce que j’ai déjà proposé par :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ;
    WITH Comptage (IdMarque, kount)
    AS 
    (SELECT z.IdMarque, COUNT(*) AS kount
     FROM   INTERVENTION AS x JOIN VEHICULE AS y ON x.IdVehicule = y.IdVehicule
               JOIN MARQUE AS z ON y.IdMarque = z.IdMarque
     GROUP BY z.IdMarque
    ) 
    UPDATE MARQUE 
        SET NbInterv = (
                        SELECT kount
                        FROM   Comptage WHERE MARQUE.IdMarque = Comptage.IdMarque   
                       ) ;

    Ou, sans WITH :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    UPDATE MARQUE 
        SET NbInterv = (
                        SELECT kount
                        FROM   (
                                 SELECT z.IdMarque, COUNT(*) AS kount
                                 FROM   INTERVENTION AS x JOIN VEHICULE AS y ON x.IdVehicule = y.IdVehicule
                                            JOIN MARQUE AS z ON y.IdMarque = z.IdMarque
                                 GROUP BY z.IdMarque
                               )  AS Comptage
                       WHERE MARQUE.IdMarque = Comptage.IdMarque 
                      ) ;

  5. #5
    Membre à l'essai
    Femme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juillet 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2012
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Tous mes voeux pour cette nouvelle année.

    Désolé pour mon absence mais j'avais besoin de quelques jours de repos.

    Waouuuuuu la requete.
    Je vous remercie énormément pour votre aide, celle la, je ne l'aurai pas trouvée.

    Elle fonctionne et me remonte les bonnes valeurs.
    Seule information, si un jour quelqu'un tombe dessus, si il n'y a pas de valeur alors la requete met un NULL. Je vais essayer de voir pour placer un 0 à la place, ca je dois pouvoir m'en sortir toute seule.

    Encore merci pour votre aide et vos remarques pertinentes.
    Merci à ce forum, bien utile !!

  6. #6
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonsoir pompom,


    Merci pour vos vœux. N’ayez pas de regrets pour votre absence, en cette période de l’année quelques jours de repos ne peuvent qu’être bénéfiques. Pour avoir été chef de projet en SSII (il y a quarante ans...), je sais ce qu’il en est !

    Concernant le bonhomme NULL qui a osé se glisser dans le résultat, on va le renvoyer dans ses vingt-deux avec un petit Coalesce.

    Requête avec WITH :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    WITH Comptage (IdMarque, kount)
    AS 
    (SELECT z.IdMarque, COUNT(*) AS kount
     FROM   INTERVENTION AS x JOIN VEHICULE AS y ON x.IdVehicule = y.IdVehicule
               JOIN MARQUE AS z ON y.IdMarque = z.IdMarque
     GROUP BY z.IdMarque
    ) 
    UPDATE MARQUE 
        SET NbInterv = COALESCE(
                                (
                                 SELECT kount
                                 FROM   Comptage WHERE MARQUE.IdMarque = Comptage.IdMarque
                                ),0)
    ;

    Sans WITH :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    UPDATE MARQUE 
        SET NbInterv = COALESCE(
                                (
                                 SELECT kount
                                 FROM   (
                                         SELECT z.IdMarque, COUNT(*) AS kount
                                         FROM   INTERVENTION AS x JOIN VEHICULE AS y 
                                                ON x.IdVehicule = y.IdVehicule
                                                    JOIN MARQUE AS z ON y.IdMarque = z.IdMarque
                                         GROUP BY z.IdMarque
                                        )  AS Comptage
                                 WHERE MARQUE.IdMarque = Comptage.IdMarque                     
                                )
                                 , 0)
    ;


    Et n’oubliez pas au besoin de mettre en œuvre les triggers évoqués par Waldar, pour que la table MARQUE soit en permanence synchrone dans sa redondance avec la table INTERVENTION (Insert, Update, Delete...) Le caprice du concepteur a un prix...


    Bonne route !

  7. #7
    Membre à l'essai
    Femme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juillet 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2012
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Merci fsmrel pour votre aide.


    C'est joliment écrit !
    Je n'aurai pas pensée comme ca !

    Encore merci a vous tous.
    Pour le trigger, c'est a voir, je vais en toucher deux mots au décideur, mais ce n'est pas le point qui me choque le plus dans son analyse ....
    Bref,
    Encore merci.

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

Discussions similaires

  1. Pb update avec sous select
    Par gnomathibus dans le forum Requêtes
    Réponses: 2
    Dernier message: 06/03/2009, 13h47
  2. Requête update avec un select
    Par housni dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 11/08/2007, 00h22
  3. Update avec un select sur la même table
    Par Xunil dans le forum Administration
    Réponses: 5
    Dernier message: 09/04/2007, 16h40
  4. [Mysql 3.23] Un UPDATE avec un SELECT
    Par griese dans le forum Langage SQL
    Réponses: 8
    Dernier message: 25/12/2006, 09h09
  5. [ SQL ] Faire un update avec un select imbriqué
    Par zozolh2 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 11/04/2005, 12h05

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