在 sql 中通过动态枢轴聚合多列

aggregate multiple columns over dynamic pivot in sql

我正在创建一个存储过程,允许用户通过提供 PersonID 数字作为参数从 2 table 中检索数据。 我想过使用枢轴函数通过 非聚合 [​​=36=] 在多个列上动态地枢转 Data table 并检索ONE 列中的数据在不同的 table 中。下面的 2 tables 只是示例数据,因为我有超过 100 列的数据 table,因此是动态部分。 2 table 没有共同的 ID 列,只有一个共同的 column_name。 这是 2 tables:

映射Table:

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

数据table:

    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
    ...          ...            ...              ...              ...

等等..

以下将动态反透视数据行,然后对字段名称与 def 数据执行联接。

如果您想 运行 此查询不带过滤器,我建议将 A.PersonID 添加到顶部 SELECT 并删除 WHERE

我应该补充一点,UNPIVOT 会更高效,但使用这种方法,无需定义 and/or 重铸值。话虽如此,表现还是很可观的。

例子

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

Returns

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

EDIT - As a Stored Procedure

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