Выполните сводную операцию с таблицей, но столкнулись с проблемой, поскольку для разделения дат на два столбца требуется несколько агрегатных функций. - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть таблица с именем hotel, которая содержит EmpId и соответствующий им столбец [check-in / out] в формате datetime.

The table looks like this

Теперь мне нужны данные в таблице чтобы выглядеть следующим образом.

Desired table

Я пробовал следующий простой запрос, и он работает правильно:

select EmpId, min([Check-in/out]) as Checkin, max([Check-in/out]) as Checkout 
from [dbo].[hotel]
group by EmpId;

Но я хочу сделать это с помощью оператора поворота в sql сервер. Я пробовал следующий запрос, но он неверный:

select EmpId, Min([Check-in/out]) AS Checkin, Max([Check-in/out]) AS Checkout  
FROM  
(select EmpId, [Check-in/out] from [dbo].[hotel]) AS SourceTable  
PIVOT  
(  
min([Check-in/out])   
FOR [Check-in/out] IN(Checkin)  
)AS PivotTable1
PIVOT
(  
max([Check-in/out])   
FOR [Check-in/out] IN(Checkout)  
)AS PivotTable2; 

Ответы [ 2 ]

0 голосов
/ 27 февраля 2020

Если значения совпадают, вы можете использовать lead() и row_number():

select c.empid, checkin, checkout
from (select c.*, [Check-in/out] as checkin,
             lead([Check-in/out]) over (partition by empid order by [Check-in/out]) as checkout,
             row_number() over (partition by empid order by [Check-in/out]) as seqnum
      from [Check-in/out] c
     ) c
where seqnum % 2 = 1;

При этом выполняются следующие вычисления:

  • Рассчитать следующую дату / время value.
  • Перечислить строки, начиная отсчет с 1.
  • Взяв нечетные строки. Это чеки.
0 голосов
/ 27 февраля 2020

Здесь снова мой комментарий в качестве ответа с примером:

Я предлагаю использовать cte / подзапросы для решения этой проблемы ... прежде всего, выберите EmpID, время и количество строк (разделение по empid и порядке по времени) - это дает вам все проверки с нечетным номером и все проверки с четным номером. Далее - на основе этого запроса - выберите empid, time и CASE WHEN. Rownumber% 2 = 0 THEN 'CHECKOUT' ELSE 'CHECKIN' END AS CheckInOut ... этот результат снова можно использовать в вашем сводном операторе

Пример :

WITH cte AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY CheckInOut) rn
  FROM T1
),
cteInOut AS(
SELECT EmpID, CheckInOut, CASE WHEN rn%2 = 0 THEN N'CheckOut' ELSE N'CheckIn' END AS CheckInOutState
  FROM cte
),
cteInOuntSrt AS(
  SELECT EmpID, CheckInOut, CheckInOutState, ROW_NUMBER() OVER (PARTITION BY EmpID, CheckInOutState ORDER BY CheckInOut) rn1
    FROM cteInOut
)
select EmpID, rn1 AS CheckIndIdx, CheckIn, CheckOut
from cteInOuntSrt
pivot
(
  min(CheckInOut)
  for CheckInOutState in ([CheckIn], [CheckOut])
) piv
ORDER BY 1, 2;

скрипка: http://sqlfiddle.com/#! 18 / af6f3 / 1/1

...