SQL查找行中的数据对并转换为列

时间:2014-03-13 18:50:43

标签: sql-server pivot

我尝试设置查询以提取员工任期报告。我有一个员工状态表,用于跟踪每个员工的信息(例如 - 雇用日期,期限日期,工资变更等)。表格如下所示:

EmployeeID    |   Date   |   Event
      1       |  1/1/99  |      1
      2       |  1/2/99  |      1
      1       |  1/3/99  |      2
      1       |  1/4/99  |      1

我使用数据透视表将表格从垂直布局移动到水平布局

SELECT        [FK_EmployeeID], MAX([1]) AS [Hire Date], ISNULL(MAX([2]), DATEADD(d, 1, GETDATE())) AS [Term Date]
FROM            DT_EmployeeStatusEvents PIVOT (MAX([Date]) FOR [EventType] IN ([1], [2])) T
GROUP BY [FK_EmployeeID]

我得到这样的结果:

EmployeeID    |   1      |   2
      1       |  1/4/99  | 1/3/99
      2       |  1/2/99  |  *null*

但是,我遇到的问题是我需要为每个员工设置两组值。 (我们雇用了很多经常性的季节性)我想要的是一种将列转换为行的方法,为每个员工选择雇用日期(1)和下一个期限日期(2),如下所示:

EmployeeID    |   1      |   2
      1       |  1/1/99  | 1/3/99
      2       |  1/2/99  |  *null*
      1       |  1/4/99  |  *null*

这可能吗?我已经查看了很多PIVOT示例,它们都显示了一个聚合函数。

2 个答案:

答案 0 :(得分:1)

问题是您试图转动datetime值,因此您只能使用maxmin作为聚合函数。当您使用这些时,每个employeeid只会返回一行。

为了解决这个问题,您需要在数据分组过程中使用一些值 - 我建议使用像row_number()这样的窗口函数。您可以创建子查询:

select employeeid, date, event
  , row_number() over(partition by employeeid, event
                      order by date) seq
from DT_EmployeeStatusEvents

SQL Fiddle with Demo。这会为每个employeeIdevent组合创建唯一值。然后将这个新数字分组,以便您可以返回多行。您完整的查询将是:

select employeeid, [1], [2]
from 
(
  select employeeid, date, event
    , row_number() over(partition by employeeid, event
                        order by date) seq
  from DT_EmployeeStatusEvents
) d
pivot
(
  max(date)
  for event in ([1], [2])
) piv
order by employeeid;

请参阅SQL Fiddle with Demo

答案 1 :(得分:0)

这应该让你开始......

DECLARE @EMP TABLE (EMPID INT, dDATE DATETIME, EVENTTYPE INT)
INSERT INTO @EMP
SELECT 1,'1/1/99',1 UNION ALL
SELECT 2,'1/2/99',1 UNION ALL
SELECT 1,'1/3/99',2 UNION ALL
SELECT 1,'1/4/99',1

SELECT EMPID, HIRE, TERM
FROM (SELECT EMPID, dDATE, 'HIRE' AS X, ROW_NUMBER() OVER(PARTITION BY EMPID, EVENTTYPE ORDER BY DDATE) AS INSTANCE FROM @EMP WHERE EVENTTYPE=1
      UNION ALL
      SELECT EMPID, dDATE, 'TERM' AS X, ROW_NUMBER() OVER(PARTITION BY EMPID, EVENTTYPE ORDER BY DDATE) AS INSTANCE FROM @EMP WHERE EVENTTYPE=2) DATATABLE
PIVOT (MIN([DDATE])
       FOR X IN ([HIRE],[TERM])) PIVOTTABLE