2013-05-28 150 views
0

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

这是我使用的测试

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

回答

0

这里有一些建议,以解决您的问题。

首先,您当前的代码不透明表中的所有列,您只需要UNPIVOT 和First_Name列。因此,我不会使用变量来获取此列的列表,只需对您需要转换的两列进行硬编码即可。

然后去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, '[email protected]+' 
     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 | 
+0

看起来非常有前途!非常感谢您这么快速的回复!我会在我们的服务器上进行测试,看看我们得到的结果是否有用。我只在示例中粘贴了几列,但源表中大约有30列。 –

+0

如何将它变成函数或视图?那可能吗? –

+0

@FedericoGiust由于您使用的是动态SQL,因此它必须位于存储过程中。动态SQL不允许在视图或函数中使用。 – Taryn