Reputation: 21
I have hunted for two days looking for what I need to no avail. I am sure this is pathetically simple as well, but this is not my bag.
The table I have stores an EmployeeID, and TimeStamp. I need to Select every other row, such that the Odd rows and even rows map to new columns Like this:
INPUT Table TimePunches:
EmployeeID Time 1 08:00:00 1 12:00:00 1 12:30:00 1 17:00:00
Ouput Table:
Employee TimeIn TimeOut 1 08:00:00 12:00:00 1 12:30:00 17:00:00
I will calc time from each output row after I figure out how to transform the rows to exactly two columns. I realize this would output garbage if it doesn't return an even number of rows, but I want to get that far first ;)
Upvotes: 2
Views: 360
Reputation: 77677
Another solution involving ROW_NUMBER()
and, for a change, 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
You can play with this query on SQL Fiddle.
Upvotes: 1
Reputation: 2760
For the record, this table structure needs to be changed, but it is possible to do what you want. This query makes me feel all kinds of dirty, and I would never consider using it in my code, but it will work, so consider yourself warned.
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
Upvotes: 0
Reputation: 78175
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
Upvotes: 0
Reputation: 66697
One solution might be, in pseudo-code:
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
To get a row at a time you can use ROW_NUMBER or cursors.
Upvotes: 0