将多行转换为单列逗号分隔 - SQL Server 2008

时间:2015-12-07 08:04:03

标签: sql-server

我想将未知数量的行转换为一列,如下所示:

我的桌子......

EMPLOYEENO NAMES        CODE        AMOUNT 
105        NAHYA ODA    BASESAL     234000
105        NAHYA ODA    249         35000
105        NAHYA ODA    250         37000
100        MAURICE RICH 249         23000
100        MAURICE RICH 250         21000
100        MAURICE RICH BASESAL     295000
107        TRINAH MYJOY 332         15000
107        TRINAH MYJOY 249         12400
107        TRINAH MYJOY LUNCHALLOW  66000
107        TRINAH MYJOY BASESAL     245000
107        TRINAH MYJOY 133         56100
107        TRINAH MYJOY 124         27400

转换成这个......

EMPLOYEENO NAMES        OTHERDEDUCT 
105        NAHYA ODA    249-35000,250-37000
100        MAURICE RICH 249-23000,250-21000
107        TRINAH MYJOY 332-15000,249-12400,133-56100,124-27400

新列“OTHERDEDUCT”应该只包含数字的CODES,不包括'baseal& lunchallow'

请在下面看到我的代码,我仍然坚持尝试合并代码&数量为一个字符串。

非常感谢您的帮助。

DECLARE @r VARCHAR(MAX), @n INT, @i INT
SELECT @i = 1,
       @r = 'SELECT EmployeeNo, Names, ' + CHAR(13),
       @n = (SELECT TOP 1 COUNT( Code )
                   FROM [platinum].[dbo].[oda]
                  GROUP BY EmployeeNo, NAMES
                  ORDER BY COUNT( Code ) DESC ) ;     
WHILE @i <= @n BEGIN
           SET @r = @r +
           CASE WHEN @i = 1 
                THEN 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + '
                                 THEN Code 
                                            ELSE SPACE(0) END ) + ' + CHAR(13)
           WHEN @i = @n
             THEN 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + '
                                 THEN '', '' + Code
                                 ELSE SPACE(0) END ) ' + CHAR(13)
             ELSE 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + '
                                 THEN '', '' + Code
                                 ELSE SPACE(0) END ) + ' + CHAR(13) 
           END ;
           SET @i = @i + 1 ;
END
SET @r = @r + '
    FROM ( SELECT EmployeeNo, Names, Code,
                  ROW_NUMBER() OVER ( PARTITION BY EmployeeNo ORDER BY Code )
             FROM [platinum].[dbo].[oda] p ) D ( EmployeeNo, Names, Code, Seq )
           GROUP BY EmployeeNo, NAMES;'
EXEC( @r ) ;

1 个答案:

答案 0 :(得分:0)

使用FOR XML PATH的STUFF对您的情况有帮助:

SELECT DISTINCT b.EMPLOYEENO,
                b.NAMES,
                Stuff((SELECT ',' + Cast(code AS VARCHAR(10)) + '-'
                              + Cast(amount AS VARCHAR(10))
                       FROM   Employee_Test a
                       WHERE  a.EMPLOYEENO = b.EMPLOYEENO
                              AND a.NAMES = b.NAMES
                              AND ISNUMERIC(A.CODE) = 1
                       FOR XML PATH('')), 1, 1, '') AS OTHERDEDUCT
FROM   Employee_Test b
WHERE  ISNUMERIC(b.CODE) = 1 --this can be done in other ways also

OR

SELECT b.EMPLOYEENO,
       b.NAMES,
       Stuff((SELECT ',' + Cast(code AS VARCHAR(10)) + '-'
                     + Cast(amount AS VARCHAR(10))
              FROM   Employee_Test a
              WHERE  a.EMPLOYEENO = b.EMPLOYEENO
                     AND a.NAMES = b.NAMES
                     AND ISNUMERIC(A.CODE) = 1
              FOR XML PATH('')), 1, 1, '') AS OTHERDEDUCT
FROM   Employee_Test b
WHERE  ISNUMERIC(b.CODE) = 1 --handling of codes only with numbers can be checked with other way as well
GROUP  BY b.EMPLOYEENO,
          b.NAMES