使用CTE将事件表行添加到列?

时间:2012-04-24 16:15:28

标签: sql-server-2005

我已经找了两天寻找我需要的东西但无济于事。我确信这也很简单,但这不是我的包。

我存储的表是EmployeeID和TimeStamp。我需要选择每隔一行,以便将奇数行和偶数行映射到新列,如下所示:

INPUT表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 

在我弄清楚如何将行转换为两列之后,我将从每个输出行计算时间。我意识到如果它没有返回偶数行,它会输出垃圾,但我想先得到那么远;)

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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或游标。

答案 3 :(得分: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