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

Développement SQL Server Discussion :

update d'une colonne depuis le resultat de deux select [2008R2]


Sujet :

Développement SQL Server

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2012
    Messages : 44
    Points : 32
    Points
    32
    Par défaut update d'une colonne depuis le resultat de deux select
    Bonjour,

    j'ai deux tables sqlserver qui se trouvent sur la même base de données :

    Table1 : Nom_utilisateur1,Montant,Date1
    Table2 : Nom_utilisateur2,Montant,Date2

    NB : les deux tables n'ont aucune clé primaire ni secondaire, le seul point commun entre eux c'est la colonne Montant.

    mon besoin est le suivant:

    en une seule requete, je souhaiterai :

    Etape 1- extraire depuis la Table1 la liste des utilisateurs (ainsi que leurs montant) ayant la date la plus récente.

    Etape 2- extraire depuis la Table2 la liste des utilisateurs (ainsi que leurs montant) ayant la date la plus récente.
    NB : tout les montant de la Table ont la valeur NULL.

    Etape 3- mettre à jours la colonne Montant de la Table2 ( uniquement pour les utilisateurs de l'étape 2 ) depuis la colonne Montant de la Table1 ( uniquement les utilisateurs de l'étape1 ).

    j'ai fournis qd même un petit effort perso et j'ai pu faire les requêtes de l'etape1 et l'etape 2 :

    Etape 1 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT
      DISTINCT [nom_utilisateur1],[Montant],[Date1]
    FROM
      [Table1] AS [derniere_date1]
    WHERE
      [Date1] = (SELECT MAX([Date1]) FROM [Table1] WHERE [nom_utilisateur1] = [derniere_date1].[nom_utilisateur1]) 
    ORDER BY [nom_utilisateur1] ASC
    Etape 2 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT
      DISTINCT [nom_utilisateur2],[Montant],[Date2]
    FROM
      [Table2] AS [derniere_date2]
    WHERE
      [Date2] = (SELECT MAX([Date2]) FROM [Table2] WHERE [nom_utilisateur2] = [derniere_date2].[nom_utilisateur2]) 
    ORDER BY [nom_utilisateur2] ASC
    il me manque donc l'etape 3 : update ... set ... en utilisant mes deux précédentes requêtes.

    merci bcp

    la bonne soirée à vous tous.

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Etapes 1 et 2 : Plutôt que de passer par une sous-requête, passe par une jointure ouverte, ça devrait être plus performant.
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT t1.Nom_utilisateur1, t1.Montant, t1.Date1
    FROM table1 t1
    LEFT OUTER JOIN table1 t2 on t2.Nom_utilisateur1 = t1.Nom_utilisateur1 and t2.Date1 > t1.Date1
    group by t1.Nom_utilisateur1, t1.Montant, t1.Date1
    HAVING count(t2.Nom_utilisateur1) = 0;

    Ensuite, j'aurais tendance à faire des CTE pour s'y retrouver :

    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
    23
    24
     
    with
    t1 (Nom_utilisateur1, Montant, Date1)
    as
    (
       SELECT t1.Nom_utilisateur1, t1.Montant, t1.Date1
       FROM table1 t1
       LEFT OUTER JOIN table1 t2 on t2.Nom_utilisateur1 = t1.Nom_utilisateur1 and t2.Date1 > t1.Date1
       group by t1.Nom_utilisateur1, t1.Montant, t1.Date1
       HAVING count(t2.Nom_utilisateur1) = 0;
    ),
    t2 (Nom_utilisateur1, Montant, Date1)
    as
    (
       SELECT t1.Nom_utilisateur1, t1.Montant, t1.Date1
       FROM table2 t1
       LEFT OUTER JOIN table2 t2 on t2.Nom_utilisateur1 = t1.Nom_utilisateur1 and t2.Date1 > t1.Date1
       group by t1.Nom_utilisateur1, t1.Montant, t1.Date1
       HAVING count(t2.Nom_utilisateur1) = 0;
    )
    update table2 t3
    set t3.Montant = t1.Montant
    inner join t1 on t1.Nom_utilisateur1 = t3.Nom_utilisateur1
    inner join t2 on t2.Nom_utilisateur1 = t3.Nom_utilisateur1;
    Sans grande certitude ceci dit...
    On ne jouit bien que de ce qu’on partage.

  3. #3
    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,

    Il serait certainement mieux de passer par des fonctions analytiques pour ce genre de choses :

    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
     
     
    ;WITH T1 AS (
    	SELECT 
    		Nom_utilisateur1
    		,Montant
    		,ROW_NUMBER() OVER(PARTITION BY Nom_utilisateur1 ORDER BY Date1 DESC) AS Rn
    	FROM table1
    )
    , T2 AS (
    	SELECT
    		Nom_utilisateur2
    		,Montant
    		,RANK() OVER(PARTITION BY Nom_utilisateur2 ORDER BY Date2 DESC) AS Rk
    	FROM Table2
    )
    UPDATE T2
    	SET Montant = T1.Montant
    FROM T2
    INNER JOIN T1 
    	ON T1.Nom_utilisateur1 = T2.Nom_utilisateur2
    WHERE T1.Rn = 1
    AND T2.Rk = 1
    Attention, si vous avez des possibilités de doublons dans la table1 sur le couple (utilisateur,date), le résultat ne sera pas déterministe. Dans ce cas il faudrait ajouter une condition pour déterminer la valeur de montant à prendre en compte.

    Deuxième remarque, vous ne spécifiez pas qu'il est nécessaire que la date maximum de la table2 soit égale à la date maximum de la table1 (pour chaque utilisateur) pour mettre à jour. Est-ce bien ce qui est voulu ?

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    C'est vrai que j'arrive pas à m'y faire... C'est pourtant tellement plus simple
    On ne jouit bien que de ce qu’on partage.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2012
    Messages : 44
    Points : 32
    Points
    32
    Par défaut
    Bonjour,

    et merci de votre aide.

    Sinon, voici en gras les réponses à vos questions :

    Attention, si vous avez des possibilités de doublons dans la table1 sur le couple (utilisateur,date), le résultat ne sera pas déterministe. Dans ce cas il faudrait ajouter une condition pour déterminer la valeur de montant à prendre en compte.
    dans les deux tables, il y a plusieurs occurrence pour presque tous les utilisateurs, par contre un utilisateur peut avoir plusieurs montants à des dates différentes ( pas à la meme date ).

    Deuxième remarque, vous ne spécifiez pas qu'il est nécessaire que la date maximum de la table2 soit égale à la date maximum de la table1 (pour chaque utilisateur) pour mettre à jour. Est-ce bien ce qui est voulu ?
    mon premier filtre serait de prendre la max date pour chaque utilisateur ( table 1 et 2 ) et d'extraire son montant.
    j'ai pas besoin de comparer les dates des deux tables.


    merci

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2012
    Messages : 44
    Points : 32
    Points
    32
    Par défaut
    c'est parfait.

    ton script répond parfaitement à mon besoin.

    merci et la bonne aprem.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 26/12/2007, 10h00
  2. Réponses: 5
    Dernier message: 15/06/2007, 16h05
  3. 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
  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