2012-04-24 16 views
2

私は2日間捜し求めて、私が役に立たないことを求めている。私はこれも哀れなほどシンプルだと確信していますが、これは私のバッグではありません。イベントテーブルの行を列に変換するCTEを使用する?

テーブルには、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 

を私がします行を正確に2つの列に変換する方法を見つけた後に、各出力行から計算時間を計算します。それは、行の偶数を返しませんが、私はそこまで最初に取得したい場合、私はこの希望出力ゴミを実現;)

答えて

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

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で遊ぶことができます。

関連する問題