Você pode usar uma subseleção ou CTE para obter os dados ordenados por funcionário e usá-los como a tabela de dados principal. Algo semelhante (adaptar se necessário) a isto:
;with ordered as (
select
emp_reader_id as empId,
CONVERT(DATE, dt) as Punch,
Row_number()
OVER (PARTITION BY emp_reader_id ORDER BY CONVERT(DATE, dt) ASC) as OrderedPunch
from trnevents
)
SELECT
entered.empId,
entered.Punch as PunchIn,
exited.Punch as PunchOut
from
ordered as entered
left join ordered as exited on
entered.empId = exited.empId
and entered.OrderedPunch + 1 = exited.OrderedPunch
Explicação:O CTE 'ordenado' mostra as entradas/saídas de funcionários ordenadas por data. O
ROW_NUMBER
é redefinido para cada funcionário (presumo que o emp_reader_id contém o ID do funcionário) por causa do PARTITION BY
. Depois de obter o contador para cada funcionário, eu junto cada soco para cada funcionário (primeira condição na junção esquerda) com o próximo soco para esse funcionário (segunda condição na junção esquerda). Dessa forma posso mostrar a coluna de entrada e a saída (o próximo soco).
Depois de obter as colunas de entrada e saída em seus dados, você pode querer excluir alguns dados (as linhas ímpares de cada funcionário são as linhas que você deseja) adicionando
WHERE entered.OrderedPunch %2 = 1