Сводная половина таблицы SQL

#sql #pivot #ssms

#sql #сводная #ssms

Вопрос:

У меня есть таблица, состоящая из информации о времени. Это в основном:

Сотрудник, дата, последовательность, время поступления, время ожидания.

Они могут отсчитывать время несколько раз в день, поэтому я пытаюсь получить все отсчеты за день в одной строке. Мой результат будет примерно таким:

Сотрудник, дата, TimeIn1, TimeOut1, TimeIn2, TimeOut2, TimeIn3, TimeOut3….

Где 1, 2 и 3 являются порядковыми номерами. Я знаю, что мог бы просто выполнить кучу левых соединений с самой таблицей на основе employee=employee, date= date и seq= seq 1, но есть ли способ сделать это в сводной таблице? Я не хочу сводить поля employee и date, только время и время ожидания.

Комментарии:

1. Я предполагаю, что поле тайм-аута null равно? Выполняется ли seq сброс на человека / день или это последовательная последовательность повсюду? 5-10 примерных строк было бы довольно удобно. Есть ли у вас жесткий лимит на количество тактовых выходов в день? Будет ли достаточно 10 тактовых входов / выходов, или вам нужно, чтобы это было более динамичным?

Ответ №1:

Короткий ответ: да, это возможно.

Точный код будет обновлен, если / когда вы предоставите образцы данных для уточнения некоторых моментов, но вы можете абсолютно pivot исключить время ожидания, оставив дату сотрудника / работы в покое.

Извините за стену кода; ни один из скриптовых сайтов не работает с моего текущего компьютера

 
declare @test table (
    pk int,
    workdate date,
    seq int,
    tIN time,
    tOUT time
)

insert into @test values 
(1, '2020-11-25', 1, '08:00', null),
(1, '2020-11-25', 2, null, '11:00'),
(1, '2020-11-25', 3, '11:32', null),
(1, '2020-11-25', 4, null, '17:00'),
(2, '2020-11-25', 5, '08:00', null),
(2, '2020-11-25', 6, null, '09:00'),
(2, '2020-11-25', 7, '09:15', null),
-- new date
(1, '2020-11-27', 8, '08:00', null),
(1, '2020-11-27', 9, null, '08:22'),
(1, '2020-11-27', 10, '09:14', null),
(1, '2020-11-27', 11, null, '12:08'),
(1, '2020-11-27', 12, '01:08', null),
(1, '2020-11-27', 13, null, '14:40'),
(1, '2020-11-27', 14, '14:55', null),
(1, '2020-11-27', 15, null, '17:00')
 
select * 
from (

  /* this just sets the column header names and condenses their values */
  select 
    pk,
    workdate,
    colName = case when tin is not null then 'TimeIn'   cast(empDaySEQ as varchar) else 'TimeOut'   cast(empDaySEQ as varchar) end,
    colValue = coalesce(tin, tout)
  from (

      /* main query */
      select 
        pk,
        workdate, 
        /* grab what pair # this clock in or out is; reset by employee amp; date */
        empDaySEQ = (row_number() over (partition by pk, workdate order by seq) / 2)   (row_number() over (partition by pk, workdate order by seq) % 2),
        tin,
        tout
      from @test
  ) i
) a 
PIVOT (
 max(colValue) 
 for colName
 IN ( /* replace w/ dynamic if you don't know upper boundary of max in/out pairs */
   [TimeIn1],
   [TimeOut1],
   [TimeIn2],
   [TimeOut2],
   [TimeIn3],
   [TimeOut3],
   [TimeIn4],
   [TimeOut4]
 )
) mypivotTable 


 

генерирует эти результаты.

(Я бы предоставил демонстрационную версию скрипки, но сегодня они у меня не работают)

Комментарии:

1. Это работает идеально, спасибо! Единственное, что мне пришлось изменить, это то, что время ввода и время ожидания записываются в одной строке, поэтому я просто объединил подзапрос временных интервалов с подзапросом тайм-аутов, а затем использовал ваш код. Большое спасибо!