在sql中通过动态数据透视聚合多个列

时间:2017-04-21 18:40:48

标签: tsql dynamic pivot

我创建了一个存储过程,允许用户通过提供PersonID号作为参数来从2个表中检索数据。 我想过使用pivot功能通过非聚合将多个列上的Data表格动态转移,并从 ONE 检索数据列在另一个表中。下面的2个表只是样本数据,因为我有超过100列的数据表,因此是动态部分。这两个表没有公共ID列,只有一个公共列名。 以下是2个表格:

映射表:

CREATE table #table (
ID varchar(10) NOT NULL,
Column_Name varchar (255) NOT NULL, 
Page_Num varchar(10) NOT NULL, 
Line_Num varchar(10) NOT NULL,
Element_Num varchar(10) NOT NULL
)

INSERT INTO #table (ID,Column_Name,Page_Num,Line_Num,Element_Num) VALUES ('1','Name', 'DT-01', '200','20')
INSERT INTO #table (ID,Column_Name,Page_Num,Line_Num,Element_Num) VALUES ('2','SSN', 'DT-02', '220','10')
INSERT INTO #table (ID,Column_Name,Page_Num,Line_Num,Element_Num) VALUES ('3','City', 'DT-03', '300','11')
INSERT INTO #table (ID,Column_Name,Page_Num,Line_Num,Element_Num) VALUES ('4','StreetName', 'DT-04', '350','33')
INSERT INTO #table (ID,Column_Name,Page_Num,Line_Num,Element_Num) VALUES ('5','Sex', 'DT-05', '310','51')

创建:

ID   Column_Name      Page_Num    Line_Num    Element_Num
_________________________________________________________________
    1    Name              DT-01         200          20
    2    SSN               DT-02         220          10
    3    City              DT-03         300          11
    4    StreetName        DT-04         350          33
    5    Sex               DT-05         310          51

数据表:

    CREATE table #temp (
PersonID varchar (100) NOT NULL,
Name varchar(100) NOT NULL,
SSN varchar (255) NOT NULL, 
City varchar(100) NOT NULL, 
StreetName varchar(100) NOT NULL,
Sex varchar(100) NOT NULL
)


INSERT INTO #temp (PersonID,Name,SSN,City,StreetName,Sex) VALUES ('112','Joe','945890189', 'Lookesville', 'Broad st','Male')
INSERT INTO #temp (PersonID,Name,SSN,City,StreetName,Sex) VALUES ('140','Santana','514819926', 'Falls Church', 'Gane Rd', 'Female')
INSERT INTO #temp (PersonID,Name,SSN,City,StreetName,Sex) VALUES ('481','Wyatt','014523548','Gainesville', 'Westfield blvd', 'Male')
INSERT INTO #temp (PersonID,Name,SSN,City,StreetName,Sex) VALUES ('724','Brittany','551489230','Aldi', 'Ostrich rd', 'Female')
INSERT INTO #temp (PersonID,Name,SSN,City,StreetName,Sex) VALUES ('100','Giovanni','774451362','Paige', 'Company ln', 'Male')

创建:

PersonID  Name         SSN            City           StreetName      Sex
    _______________________________________________________________________
    112     Joe      945890189     Lookesville         Broad st      Male
    140    Santana   514819926     Falls Church        Gane Rd       Female
    481     Wyatt    014523548     Gainesville         Westfield rd  Male
    724    Brittany  551489230     Aldi                Ostrich rd    Female
    100    Giovanni  774451362     Paige               Company ln    Male

最终结果应该是: 示例:用户输入参数PersonID = 140

   Column_name   Page_Num      Line_Num       Element_Num       Data
    _____________________________________________________________________________
    Name         DT-01          200              20             Santana
    SSN          DT-02          220              10             514819926
    City         DT-03          300              11            Falls Church
    StreetName   DT-04          350              33              Gane Rd
    Sex          DT-05          310              51              Female
    ...          ...            ...              ...              ...

依旧......

1 个答案:

答案 0 :(得分:0)

以下内容将动态展开数据行,然后使用def数据对字段名称执行连接。

如果您想在没有过滤器的情况下运行此查询,我建议您将A.PersonID添加到顶部SELECT并删除WHERE

我应该补充一点, UNPIVOT 会更高效,但是使用这种方法,不需要定义和/或重铸值。也就是说,表现仍然非常可观。

示例

Select D.*
      ,Data=C.Value
 From  #Temp A
 Cross Apply (Select XMLData = cast((Select A.* For XML Raw) as xml)) B
 Cross Apply (
                Select Item   = attr.value('local-name(.)','varchar(100)')
                      ,Value  = attr.value('.','varchar(max)') 
                 From  B.XMLData.nodes('/row') as X(r)
                 Cross Apply X.r.nodes('./@*') AS N(attr)
             ) C
 Join  #Table D on (C.Item=D.Column_Name)
 Where PersonID=140

<强>返回

enter image description here

如果它有助于可视化,则CROSS APPLY C会生成以下内容:

enter image description here

  

编辑 - 作为存储过程

CREATE PROCEDURE [dbo].[YourProcedureName](@PersonID int) 

As

Begin
    Set NoCount On;

    Select D.*
          ,Data=C.Value
     From  YourPersonTableName A
     Cross Apply (Select XMLData = cast((Select A.* For XML Raw) as xml)) B
     Cross Apply (
                    Select Item   = attr.value('local-name(.)','varchar(100)')
                          ,Value  = attr.value('.','varchar(max)') 
                     From  B.XMLData.nodes('/row') as X(r)
                     Cross Apply X.r.nodes('./@*') AS N(attr)
                 ) C
     Join  YourObjectTableName D on (C.Item=D.Column_Name)
     Where PersonID=@PersonID

End