2012-04-24 40 views
2

我已经追捕了两天寻找我不需要的东西。我相信这很简单,但这不是我的包。事件表行到列使用CTE?

表中我存储了一个EmployeeID和TimeStamp。我需要选择每隔一行,使得奇数行和偶数行映射到新列像这样:

输入表TimePunches:

 
EmployeeID  Time 
1    08:00:00 
1    12:00:00 
1    12:30:00 
1    17:00:00 

输出继电器表:

 
Employee  TimeIn  TimeOut 
1    08:00:00  12:00:00 
1    12:30:00  17:00:00 

我会计算出每个输出行的计算时间,然后找出如何将行转换为两列。我知道这将输出的垃圾,如果它不返回偶数行,但我想走到这一步第一;)

回答

0
with prepared_data as (
    select 
    EmployeeID, 
    Time, 
    row_number() over(partition by EmployeeID order by Time) as num 
    from TimePunches 
) 
select 
    p1.EmployeeID, 
    p1.Time as TimeIn, 
    p2.Time as TimeOut 
from 
    prepared_data p1 
    left join prepared_data p2 on p1.EmployeeID = p2.EmployeeID and p1.num + 1 = p2.num 
where 
    p1.num % 2 = 1 
order by 
    p1.EmployeeID, 
    p1.num 
+0

编辑完成后,它就像一个魅力。我不知道该怎么感谢你才足够。哦,等等...我在哪里发送支票? :) – user1354197 2012-04-24 22:09:33

0

一种解决方案是,在伪代码:

declare @timeIn datetime, @timeOut datetime 
declare @emp int 

get one row at a time { 

if (row is even) 
    @timeIn = Time from row 
} 
else { 
    @timeOut = Time from row 
    @emp = Employee from row 
    insert into #tempTable @emp, @timeIn, @timeOut 
} 

select #tempTable 

要一次获得一行,可以使用ROW_NUMBER或游标。

0

为了记录,这个表结构需要改变,但它可以做你想做的。这个查询让我觉得各种各样的肮脏,我永远不会考虑在我的代码中使用它,但它会工作,所以认为你自己警告。

with rank1 as (
SELECT EmployeeID, Time, RANK() OVER (PARTITION BY EmployeeID ORDER BY Time) as rank 
FROM TimePunches), 
rank2 as (
SELECT EmployeeID, Time, RANK() OVER (PARTITION BY EmployeeID ORDER BY Time) as rank 
FROM TimePunches) 

SELECT rank1.EmployeeID, rank1.Time as timeIn, rank2.Time as timeOut 
FROM rank1 
JOIN rank2 on rank1.EmployeeID = rank2.EmployeeID AND rank1.rank % 2 = 1 AND rank1.rank - (rank1.rank % 2) = rank2.rank 
1

另一种解决方案涉及ROW_NUMBER()和,换一换,PIVOT

WITH prepared AS (
    SELECT 
    EmployeeID, 
    Time, 
    TimeRow = (ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY Time) - 1)/2 
    TimeKind = 
     CASE (ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY Time) - 1) % 2 
     WHEN 0 THEN 'TimeIn' 
     WHEN 1 THEN 'TimeOut' 
     END 
    FROM TimePunches 
) 
SELECT 
    EmployeeID, 
    TimeIn, 
    TimeOut 
FROM prepared 
PIVOT (
    MAX(Time) FOR TimeKind IN (TimeIn, TimeOut) 
) p 
ORDER BY 
    EmployeeID, 
    TimeRow 

您可以使用此查询on SQL Fiddle玩。