如何从数据透视表创建多个表

时间:2013-04-09 22:15:05

标签: mysql sql sql-server ssis pivot

我有一个生成如下的数据透视表,Name包含列名和文本包含它们的值,所以需要根据相似的值生成多个表

输入表

ID  Name    text    
1   Name,DOB    John,02/02/1980 
2   FirstName,SSN,City  Ray,987898789,Chicago   
3   Name,DOB    Mary,12/21/1990 
4   FirstName,SSN,City  Cary,987000789,Dallas   
5   PersonID,Code,Zip,Gender,Maritial   1234,A456,23456,M,single    
6   PersonID,Code,Zip,Gender,Maritial   1235,A457,23233,M,single    
7   PersonID,Code,Zip,Gender,Maritial   1236,A458,67675,M,Married   

因此输出表应该类似于

输出表1

ID  Name    DOB 
1   john    02/02/1980  
3   Mary    02/02/1980  

输出表2

ID  FirstName   SSN City
2   Ray 987898789   Chicago
4   Cary    987000789   Dallas

输出表3

ID  PersonID    Zip Gender  Marital 
5   1234    A456    23456   M   Single  
6   1235    A457    23233   M   Single  
7   1236    A458    67675   M   Married 

有人可以帮我解决这个问题。这可以在Sqlserver或MySQL或SSIS中完成吗?

1 个答案:

答案 0 :(得分:2)

我的建议是首先规范你的input表格。在SQL Server中,您可以使用递归CTE将逗号分隔列表中的数据拆分为行。

CTE将类似于以下内容:

;with cte (id, col, Name_list, value, text_list) as
(
  select id,
    cast(left(Name, charindex(',',Name+',')-1) as varchar(50)) col,
         stuff(Name, 1, charindex(',',Name+','), '') Name_list,
    cast(left(text, charindex(',',text+',')-1) as varchar(50)) value,
         stuff(text, 1, charindex(',',text+','), '') text_list
  from input
  union all
  select id,
    cast(left(Name_list, charindex(',',Name_list+',')-1) as varchar(50)) col,
    stuff(Name_list, 1, charindex(',',Name_list+','), '') Name_list,
    cast(left(text_list, charindex(',',text_list+',')-1) as varchar(50)) value,
         stuff(text_list, 1, charindex(',',text_list+','), '') text_list
  from cte
  where Name_list > ''
    or text_list > ''
) 
select id, col, value
from cte;

SQL Fiddle with Demo。这将以格式提供数据:

| ID |       COL |      VALUE |
-------------------------------
|  1 |      Name |       John |
|  2 | FirstName |        Ray |
|  3 |      Name |       Mary |
|  4 | FirstName |       Cary |
|  5 |  PersonID |       1234 |

一旦数据采用该格式,您就可以根据每个表中所需的列对数据进行PIVOT。

例如,如果您想要Table1的数据,您将使用:

;with cte (id, col, Name_list, value, text_list) as
(
  select id,
    cast(left(Name, charindex(',',Name+',')-1) as varchar(50)) col,
         stuff(Name, 1, charindex(',',Name+','), '') Name_list,
    cast(left(text, charindex(',',text+',')-1) as varchar(50)) value,
         stuff(text, 1, charindex(',',text+','), '') text_list
  from input
  union all
  select id,
    cast(left(Name_list, charindex(',',Name_list+',')-1) as varchar(50)) col,
    stuff(Name_list, 1, charindex(',',Name_list+','), '') Name_list,
    cast(left(text_list, charindex(',',text_list+',')-1) as varchar(50)) value,
         stuff(text_list, 1, charindex(',',text_list+','), '') text_list
  from cte
  where Name_list > ''
    or text_list > ''
) 
select *
-- into table1
from
(
  select id, col, value
  from cte
  where col in ('Name', 'DOB')
) d
pivot
(
  max(value)
  for col in (Name, DOB)
) piv;

请参阅SQL Fiddle with Demo

然后,您将使用下一个表的值替换每个查询中的列名称。