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 :

Concaténer les réponses d'un select


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 72
    Points : 77
    Points
    77
    Par défaut Concaténer les réponses d'un select
    Bonjour

    J'ai une table ressemblant à peu de chose prés à ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    IdProjet                         IdDette                     TypeProjet    
    ---------                  --------------               --------------
    1                                     1                                 1
    1                                     2                                 3
    1                                     3                                 1
    1                                     4                                 11
    1                                     5                                 13
    1                                     6                                 3
    Je recherche à un moyen de concatener toutes les id par type de projet et par IdProjet

    Au final je souhaite à terme réaliser ceci comme résultat final

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IdProjet                         IdDette                     TypeProjet    
    ---------                  --------------               --------------
    1                                     1 , 3                             1
    1                                     2 , 6                             3
    1                                     4                                 11
    1                                     5                                 13
    Sachant que je ne souhaite que pour 1 id et qu'il y'a maximum 13 type de projet.

    J'ai actuellement ceci

    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
    BEGIN
    	SET NOCOUNT ON;
     
    	DECLARE @ID_PROJET INT
    	SET @ID_PROJET = 1
    	DECLARE @COMPTEUR INTEGER
    	SET @COMPTEUR = 0
    	DECLARE @LIMITE INTEGER
    	SET @LIMITE = 13
    	DECLARE @VALEUR INTEGER
    	DECLARE @PASSAGE INTEGER
     
    	WHILE (@COMPTEUR <= @LIMITE)
    		BEGIN
    			SELECT @VALEUR = count(fd.Type)
    				from dbo.FinancementDette as fd 
    				where fd.IdProjet = @ID_PROJET
    				and fd.Type = @COMPTEUR
     
    			IF (@VALEUR > 0)
     
    					SELECT fd.Id, fd.Type
    					from dbo.FinancementDette as fd 
    					where fd.IdProjet = @ID_PROJET
    					and fd.Type = @COMPTEUR 
     
    			SET @COMPTEUR = @COMPTEUR+1	
    		END
    END
    Cette procedure fonctionne bien mais je dois maintenant faire une concatenation de chaque resultat de colonne puis un UNION pour remettre toutes ces données sous un seul resultat

    Voila le resultat aujourdh'ui
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    IdProjet                         IdDette                     TypeProjet    
    ---------                  --------------               --------------
    1                                     1                                1
    1                                     3                                1
     
    IdProjet                         IdDette                     TypeProjet    
    ---------                  --------------               --------------
    1                                     2                                1
    1                                     6                                3
    etc

    Auriez vous une idée pour la suite de ma procédure car je bloque.

    Merci de vos futures réponses

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Par exemple, en une seule requête.

    Données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    DECLARE @MaTable TABLE
    (
      IdProjet   tinyint,
      IdDette    tinyint,
      TypeProjet tinyint
    );
     
    INSERT INTO @MaTable
    select 1, 1,  1 union all
    select 1, 2,  3 union all
    select 1, 3,  1 union all
    select 1, 4, 11 union all
    select 1, 5, 13 union all
    select 1, 6,  3;
    Requête
    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
    With CTInit (IdProjet, IdDette, TypeProjet, RNA, RND)
    AS
    (
    select IdProjet, cast(IdDette as varchar(max)), TypeProjet,
           row_number() over(partition by IdProjet, TypeProjet order by IdDette  asc),
           row_number() over(partition by IdProjet, TypeProjet order by IdDette desc)
      from @MaTable
    )
      ,  CTRec (IdProjet, IdDette, TypeProjet, RNA, RND)
    AS
    (
    select IdProjet, IdDette, TypeProjet, RNA, RND
      from CTInit
     where RNA = 1
     union all
    select R.IdProjet, R.IdDette + ', ' + I.IdDette, R.TypeProjet, I.RNA, I.RND
      from CTRec AS R
           inner join CTInit AS I
             on I.IdProjet   = R.IdProjet
            and I.TypeProjet = R.TypeProjet
            and I.RNA        = R.RNA + 1
    )
      select IdProjet, IdDette, TypeProjet
        from CTRec
       where RND = 1
    order by IdProjet ASC, TypeProjet ASC;
    Résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IdProjet IdDette TypeProjet
    -------- ------- ----------
    1        1, 3    1
    1        2, 6    3
    1        4       11
    1        5       13
    Il y a peut-être plus simple en utilisant le XML Path.

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    La syntaxe est effectivement beaucoup plus courte avec le FOR XML PATH :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT b.IdProjet,
           STUFF( (SELECT ', ' + cast(IdDette as varchar)
                   FROM @MaTable AS a
                   WHERE b.IdProjet   = a.IdProjet
                     AND b.TypeProjet = a.TypeProjet
                   FOR XML PATH('')),1 ,1, '')) AS IdDette,
           b.TypeProjet
    FROM @MaTable AS b
    GROUP BY b.IdProjet, b.TypeProjet;

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 72
    Points : 77
    Points
    77
    Par défaut
    Je vous remercie grandement Waldar pour votre aide précieuse

  5. #5
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Pour avoir testé les 2 méthodes sur des gros volumes de données , j'ai trouvé que la concaténation des données via XML PATH était beaucoup plus rapide ... La méthode via les CTE récursives étaient même plus longue que d'employer un curseur

    Si qqn a des retours la dessus ...

    ++

  6. #6
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Même chose pour moi : l'utilisation de la récursivité sur des gros volumes est contre-performante, surtout quand un parent peut avoir plusieurs enfants : dans ce cas SQL Server ne peut pas estimer proprement ... et comme d'habitude, c'est contre-performant

    L'utilisation de la clause FOR XML PATH ('') est de loin la plus rapide lorsqu'il y a besoin de réaliser de la concaténation, et l'expression de la requête n'en est que plus simple

    @++

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/02/2012, 17h56
  2. Récupérer les valeurs d'un <select> multiple
    Par vg33 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 25/10/2005, 11h38
  3. cacher les options d'un select
    Par soony dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 07/09/2005, 10h05
  4. Formater les libelles dans un <select>
    Par ranx dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 25/08/2005, 13h30
  5. Réponses: 15
    Dernier message: 21/06/2004, 16h52

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