如何旋转多个列并保持它们的关系

时间:2016-10-13 20:18:06

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

我一直在墙上撞墙3天,所以希望有人可以帮助我。

我有一组数据,我需要做一些转向,但不能完全理解语法。

示例数据集:

Employee    LastName    FirstName   Status  Location    GroupBU     DeductionDesc   Active      Field                   Value
----------------------------------------------------------------------------------------------------------------------------------
12345       SMITH       JOHN            A       5555        9999    LIFE INS CHILD      Y       Deduction               8502
12345       SMITH       JOHN            A       5555        9999    LIFE INS CHILD      Y       EmployeeAmtPct          0.1
12345       SMITH       JOHN            A       5555        9999    LIFE INS CHILD      Y       EmployeeAnnSalary       10000
12345       SMITH       JOHN            A       5555        9999    LIFE INS CHILD      Y       EmployeeInsAmt          10000
67890       SMITH       JANE            A       5555        9999    LIFE INS SPOUSE     Y       Deduction               8501
67890       SMITH       JANE            A       5555        9999    LIFE INS SPOUSE     Y       EmployeeAmtPct          0.357
67890       SMITH       JANE            A       5555        9999    LIFE INS SPOUSE     Y       EmployeeAnnSalary       50000
67890       SMITH       JANE            A       5555        9999    LIFE INS SPOUSE     Y       EmployeeInsAmt          50000

期望的结果:

Employee    LastName    FirstName   Status  Location    GroupBU [LIFE INS CHILD]    Deduction   EmployeeAmtPct  EmployeeAnnSalary   EmployeeInsAmt  [LIFE INS SPOUSE]   Deduction   EmployeeAmtPct  EmployeeAnnSalary   EmployeeInsAmt
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
12345       SMITH       JOHN        A       5555        9999    LIFE INS CHILD      8502        0.1             10000               10000           NULL                NULL        NULL            NULL                NULL
67890       SMITH       JANE        A       5555        9999    NULL                NULL        NULL            NULL                NULL            LIFE INS SPOUSE     8501        0.357           50000               50000

显然,在我的“Desired Outcome”中,我有重复的列名,这将不起作用,所以我假设我需要想出一种方法来为每个列添加/添加一些东西以便制作它们是独一无二的,但却无法弄清楚如何做到这一点。这也是将不同的Field&最终输出中相应“DeductionDesc”的值。还要求“DeductionDesc”中的值是最终输出中的列名,如果值不存在,则它只是NULL(在输出中演示)。

我的源数据是使用UNPIVOT创建的,因为它似乎会使它更有可能成功。

我在“DeductionDesc”中有大约65个唯一值,以及大约3500个唯一员工记录。

这是我的代码的当前(和第4次迭代):

select * 
from
    (
    select Employee,LastName,FirstName,Status,Location,GroupBU,DeductionDesc,Active,Field,Value 
    FROM MyTable
    ) unpvt
PIVOT 
    (
    MAX([DeductionDesc])
    FOR [DeductionDesc] IN ([LIFE INS SPOUSE],[LIFE INS CHILD UNUM POST TAX])
    ) pvt
PIVOT 
    (
    MAX([Value])
    FOR [Field] IN ([InsPlan],[EmployeeAnnSalary],[InsCoverage],[InsEmployeeRate],[EmployeeAmtPct],[InsLevelDesc],[InsCoverageDesc],[InsCarrierDesc],[InsPlanDesc],[InsLevel],[Deduction],[EmployeeInsAmt],[InsCarrier])
    ) pvt

为了便于阅读和简单起见,我在“IN”声明中删除了第一个PIVOT中的大部分项目,但最初在那里列出了所有65项。

任何人都可以提供帮助以达到我想要的结果的任何帮助将不胜感激。如果需要其他信息,请告诉我。 谢谢!

2 个答案:

答案 0 :(得分:0)

这里假设SQL Server语法,但这个概念适用于大多数SQL风格。攻击它的一种方法是使用CASE结构:

SELECT tA.Employee, tA.LastName, tA.FirstName, tA.Status, tA.Location,    
       tA.GroupBU, tB.Deduction, tB.EmployeeAmtPct

FROM your_table AS tA 

INNER JOIN

(SELECT Employee, SUM(CASE WHEN Field = 'Deduction'      THEN Value ELSE 0 END) AS Deduction,
                  SUM(CASE WHEN Field = 'EmployeeAmtPct' THEN Value ELSE 0 END) AS EmployeeAmtPct
                  ...and so on for all the fields that you want to transpose...
 FROM your_table 
 GROUP BY Employee) AS tB ON tA.Employee = tB.Employee

为了简洁起见,我只是将Deduction和EmployeeAmtPct放在这里。基本上,这是一个交叉制表查询。它只是根据“Field”属于哪个类别进行选择性求和。 CASE语句中的ELSE子句确保始终存在要求和的值。

答案 1 :(得分:0)

如果您不介意动态(将#myTable更改为您的表名)

Declare @SQL varchar(max) = ''

Select @SQL = @SQL +SqlExpr
 From (
        Select Top 100 Percent *
              ,SqlExpr = case when ColNr=1 then char(13)+','+QuoteName(DeductionDesc)+'=max(case when DeductionDesc='''+DeductionDesc+''' and Field='''+Field+''' then DeductionDesc else null end)' else '' end +char(13)+','+QuoteName(Field)+'=max(case when DeductionDesc='''+DeductionDesc+''' and Field='''+Field+''' then Value else null end)'
         From (
                Select Distinct 
                       DeductionDesc
                      ,Field
                      ,ColNr  = Row_Number() over (Partition By DeductionDesc Order By Field)
                 From  #MyTable
              ) A Order By 1,3
      ) A 

Select @SQL = '
Select Employee
      ,LastName
      ,FirstName
      ,Status
      ,Location
      ,GroupBU'+@SQL+'
 From  #MyTable
 Group By 
       Employee
      ,LastName
      ,FirstName
      ,Status
      ,Location
      ,GroupBU 
'
--Print(@SQL)
Exec(@SQL)

返回

enter image description here