121 votes

Méthode optimale pour concaténer/agréger des chaînes de caractères

Je cherche un moyen d'agréger des chaînes de caractères de différentes lignes en une seule ligne. J'ai l'intention de le faire à plusieurs endroits différents, et il serait bon de disposer d'une fonction pour faciliter cette opération. J'ai essayé des solutions utilisant COALESCE y FOR XML mais ils ne sont pas à la hauteur pour moi.

L'agrégation de chaînes de caractères donnerait quelque chose comme ça :

id | Name                    Result: id | Names
-- - ----                            -- - -----
1  | Matt                            1  | Matt, Rocks
1  | Rocks                           2  | Stylus
2  | Stylus

J'ai jeté un coup d'oeil à Fonctions agrégées définies par CLR en remplacement de COALESCE y FOR XML mais apparemment SQL Azure n'est pas ne prend pas en charge les éléments définis par le CLR, ce qui est pénible pour moi, car je sais que le fait de pouvoir les utiliser résoudrait un grand nombre de mes problèmes.

Existe-t-il une solution de contournement ou une méthode optimale similaire (qui n'est peut-être pas aussi optimale que CLR, mais Je prends ce que je peux avoir) que je peux utiliser pour agréger mes affaires ?

0 votes

De quelle manière for xml ne fonctionne pas pour vous ?

4 votes

Cela fonctionne, mais j'ai jeté un coup d'oeil au plan d'exécution et chaque for xml montre une utilisation de 25% en termes de performance de la requête (un gros de la requête !)

2 votes

Il y a différentes façons de faire le for xml path la requête. Certaines sont plus rapides que d'autres. Cela peut dépendre de vos données mais celles qui utilisent distinct est, selon mon expérience, plus lent que l'utilisation de group by . Et si vous utilisez .value('.', nvarchar(max)) pour obtenir les valeurs concaténées, vous devez changer cela en .value('./text()[1]', nvarchar(max))

5voto

jvc Points 73

Vous pouvez utiliser += pour concaténer des chaînes de caractères, par exemple :

declare @test nvarchar(max)
set @test = ''
select @test += name from names

si vous sélectionnez @test, cela vous donnera tous les noms concaténés

0 votes

Veuillez préciser le dialecte ou la version de SQL depuis quand il est supporté.

0 votes

Cela fonctionne dans SQL Server 2012. Notez qu'une liste séparée par des virgules peut être créée avec select @test += name + ', ' from names

4 votes

Cela utilise un comportement non défini, et n'est pas sûr. Cette méthode est particulièrement susceptible de donner un résultat étrange/incorrect si vous avez un objet de type ORDER BY dans votre requête. Vous devez utiliser l'une des alternatives listées.

2voto

Tom Halladay Points 2387

J'ai trouvé la réponse de Serge très prometteuse, mais j'ai également rencontré des problèmes de performance avec cette réponse telle qu'elle est écrite. Cependant, lorsque je l'ai restructurée pour utiliser des tables temporaires et ne pas inclure les tables CTE doubles, les performances sont passées de 1 minute 40 secondes à moins d'une seconde pour 1000 enregistrements combinés. Le voici pour tous ceux qui ont besoin de faire cela sans FOR XML sur les anciennes versions de SQL Server :

DECLARE @STRUCTURED_VALUES TABLE (
     ID                 INT
    ,VALUE              VARCHAR(MAX) NULL
    ,VALUENUMBER        BIGINT
    ,VALUECOUNT         INT
);

INSERT INTO @STRUCTURED_VALUES
SELECT   ID
        ,VALUE
        ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY VALUE) AS VALUENUMBER
        ,COUNT(*) OVER (PARTITION BY ID)    AS VALUECOUNT
FROM    RAW_VALUES_TABLE;

WITH CTE AS (
    SELECT   SV.ID
            ,SV.VALUE
            ,SV.VALUENUMBER
            ,SV.VALUECOUNT
    FROM    @STRUCTURED_VALUES SV
    WHERE   VALUENUMBER = 1

    UNION ALL

    SELECT   SV.ID
            ,CTE.VALUE + ' ' + SV.VALUE AS VALUE
            ,SV.VALUENUMBER
            ,SV.VALUECOUNT
    FROM    @STRUCTURED_VALUES SV
    JOIN    CTE 
        ON  SV.ID = CTE.ID
        AND SV.VALUENUMBER = CTE.VALUENUMBER + 1

)
SELECT   ID
        ,VALUE
FROM    CTE
WHERE   VALUENUMBER = VALUECOUNT
ORDER BY ID
;

-1voto

Neil Points 774

J'ai raté quelque chose ou vous pouvez simplement faire + ? De plus, vous avez demandé comment le faire à partir de différentes colonnes, mais votre exemple porte sur différentes lignes.

http://msdn.microsoft.com/en-us/library/windowsazure/ee336263.aspx#other

  • (Opérateur de concaténation de chaînes de caractères) - Le signe plus (+) est l'opérateur qui permet de concaténer des chaînes de caractères.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X