动态数据透视表MS SQL 2008

时间:2013-05-28 14:41:15

标签: sql-server sql-server-2008 tsql pivot

我正在尝试创建一个动态数据透视表,以便在不同的列而不是行中获得结果。

这是我用来测试的表

CREATE TABLE [dbo].[Authors](
[Client_Id] [nvarchar](50) NOT NULL,
[Project_Id] [nvarchar](50) NOT NULL,
[Person_Id] [int] NOT NULL,
[Author_Number] [int] NOT NULL,
[Family_Name] [nvarchar](50) NULL,
[First_Name] [nvarchar](50) NULL,
)

INSERT INTO Authors (Client_Id, Project_Id, Person_Id, Author_Number, Family_Name, First_Name)
VALUES ('TEST','TEST',12345,1,'Giust','Fede')
INSERT INTO Authors (Client_Id, Project_Id, Person_Id, Author_Number, Family_Name, First_Name)
VALUES ('TEST','TEST',12345,2,'Giust','Fede')
INSERT INTO Authors (Client_Id, Project_Id, Person_Id, Author_Number, Family_Name, First_Name)
VALUES ('TEST','TEST',12346,1,'Giust','Fede')
INSERT INTO Authors (Client_Id, Project_Id, Person_Id, Author_Number, Family_Name, First_Name)
VALUES ('TEST','TEST',12346,2,'Giust','Fede')
INSERT INTO Authors (Client_Id, Project_Id, Person_Id, Author_Number, Family_Name, First_Name)
VALUES ('TEST','TEST',12346,3,'Giust','Fede')

到目前为止,我得到了这样的结果

CLIENT_ID   PROJECT_ID  PERSON_ID   AUTHOR_NUMBER   FAMILY_NAME FIRST_NAME
TEST        TEST        12345       1               Giust       Fede
TEST        TEST        12345       2               Ma          Ke
TEST        TEST        12346       1               Jones       Peter
TEST        TEST        12346       2               Davies      Bob
TEST        TEST        12346       3               Richards        Craig

我需要结果像这样出来,并且是动态的,因为有时候我可以有2位作者,或者10位作者。

CLIENT_ID   PROJECT_ID  PERSON_ID   FAMILY_NAME_1   FIRST_NAME_1    FAMILY_NAME_2   FIRST_NAME_2        FAMILY_NAME_3   FIRST_NAME_3      
TEST        TEST        12345       Giust           Fede            Ma              Ke

TEST        TEST        12346       Jones           Peter           Davies          Bob                 Richards            Craig

我一直在尝试使用此代码,但不断收到错误

SQL Fiddle

1 个答案:

答案 0 :(得分:0)

以下是一些解决您问题的建议。

首先,您当前的代码忽略了表中的所有列,您只需要取消Family_NameFirst_Name列的UNPIVOT。因此,我不会使用变量来获取列的列表,只需硬编码您需要解开的两列。

然后要获取PIVOT的列列表,请更改代码以使用Author_number,然后使用列名为Family_NameFirst_Name的字符串:

select @colsPivot = STUFF((SELECT ',' + QUOTENAME(c.col + '_'+cast(Author_Number as varchar(10))) 
                    from Authors
                    cross apply
                    (
                      select 'Family_Name' col, 1 so union all
                      select 'First_Name', 2
                    ) c
                    group by col, author_number, so
                    order by author_number, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

这给出了cols列表:

|                                                                                     COLUMN_0 |
------------------------------------------------------------------------------------------------
| [Family_Name_1],[First_Name_1],[Family_Name_2],[First_Name_2],[Family_Name_3],[First_Name_3] |

对代码进行这些更改后,最终查询将是

DECLARE @colsPivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @colsPivot = STUFF((SELECT ',' + QUOTENAME(c.col + '_'+cast(Author_Number as varchar(10))) 
                    from Authors
                    cross apply
                    (
                      select 'Family_Name' col, 1 so union all
                      select 'First_Name', 2
                    ) c
                    group by col, author_number, so
                    order by author_number, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query 
  = 'select Client_id, Project_id, Person_Id, '+@colsPivot+' 
      from
      (
        select Client_id, Project_id, Person_Id, 
          col+''_''+cast(Author_Number as varchar(10)) col, val
        from
        (
          select Client_id, Project_id,
            Person_Id, 
            Author_Number, 
            Family_Name, 
            First_Name
          from Authors
        ) s
        unpivot
        (
          val
          for col in (Family_Name, First_Name)
        ) u
      ) x1
      pivot
      (
        max(val)
        for col in ('+ @colspivot +')
      ) p'

exec(@query)

SQL Fiddle with Demo。这给出了一个结果:

| CLIENT_ID | PROJECT_ID | PERSON_ID | FAMILY_NAME_1 | FIRST_NAME_1 | FAMILY_NAME_2 | FIRST_NAME_2 | FAMILY_NAME_3 | FIRST_NAME_3 |
-----------------------------------------------------------------------------------------------------------------------------------
|      TEST |       TEST |     12345 |         Giust |         Fede |            Ma |           Ke |        (null) |       (null) |
|      TEST |       TEST |     12346 |         Jones |        Peter |        Davies |          Bob |      Richards |        Craig |