Faire une concaténation sur un résultat d’une requête

Premier cas : Concaténer le résultat d'une colonne sur une ligne

Le principe est d'empiler les résultats d'un
SELECT dans une variable.

Prenons un exemple sur la table
HumanResources.Department de la base exemple de SQL Server 2005,
AdventureWorks.

Concaténons le nom des départements.

USE AdventureWorks

DECLARE @DptName varchar(max);

SET @DptName =
'';

select @DptName= @DptName +
COALESCE(Name
+',','')
from HumanResources.Department;

IF @DptName IS
NOT
NULL

SET @DptName =
SUBSTRING(@DptName,1,LEN(@DptName)-1)

SELECT @DptName

 

Cette méthode possède l'avantage de travailler de manière ensembliste et ne fait pas appel à un curseur.

 

Deuxième cas : Concaténer les lignes jointes

Traitons ce cas de trois manières et comparons le temps CPU à l'aide de l'instruction set
statistics
time
ON.

Le premier cas de figure utilise une fonction explicitement crée

 

CREATE FUNCTION dbo.GetMedalResult

(

    @CustomerID bigint

)

RETURNS
VARCHAR(max)

AS

BEGIN

    DECLARE @r VARCHAR(max)

      SET  @r =
''

    SELECT @r = @r +
COALESCE(convert(varchar(max),SalesOrderID )+',',
'')        

        FROM Sales.SalesOrderHeader

        WHERE CustomerID = @CustomerID

      IF @r <>
''

      SET @r =
SUBSTRING(@r,1,LEN(@r)-1)

    RETURN @r

END

GO

 

La requête

SELECT   CustomerID, dbo.GetMedalResult(CustomerID)

FROM Sales.Customer

order by CustomerID

retourne le tableau suivant

CustomerID

SalesOrderIDs

1

43860,44501,45283,46042

2

46976,47997,49054,50216,51728,57044,63198,69488

3

44124,44791,45568,46377,47439,48378,49538,50748,53616,59011,65310,71889

 

Temps CPU :

Sur mon environnement de travail, j'obtiens les résultats suivant :

CPU time = 3588 ms, elapsed time = 3702 ms.

 

Le deuxième cas de figure s'appuie sur les fonctionnalités de XML incluses dans le moteur SQL Server.

 

USE AdventureWorks

GO

 
 

SELECT

    CustomerID,

    SalesOrderIDs =
REPLACE(

        (

            SELECT

                SalesOrderID AS [data()]

            FROM

                Sales.SalesOrderHeader soh

            WHERE

                soh.CustomerID = c.CustomerID

            ORDER
BY

                SalesOrderID

            FOR
XML
PATH
('')

        ),
' ',
',')

FROM

    Sales.Customer c

ORDER
BY

    CustomerID

 

Temps CPU :

--CPU time = 265 ms, elapsed time = 378 ms.

Le temps CPU est divisé par plus de 10 en utilisant la les fonctionnalités de XML incluses dans le moteur SQL Server. La fonction data renvoie les éléments sur une même ligne séparée d'un espace.

 
 

Le troisième cas de figure s'appuie sur en plus des XML de la nouvelle clause SQL Server 2005 CROSS APPLY

 
 

USE AdventureWorks

GO

 
 

SELECT

    CustomerID,

    SalesOrderIDs =
LEFT(o.list,
LEN(o.list)-1)

FROM

    Sales.Customer c

CROSS
APPLY

(

        SELECT

            CONVERT(VARCHAR(12), SalesOrderID)
+
','
AS [text()]

        FROM

            Sales.SalesOrderHeader s

        WHERE

            s.CustomerID = c.CustomerID

        ORDER
BY

            SalesOrderID

        FOR
XML
PATH('')

    ) o (list)

ORDER
BY

    CustomerID

Temps CPU :

CPU time = 218 ms, elapsed time = 330 ms.

Le temps CPU est légèrement plus performant que le précédant cas de figure.