2015-04-08 3 views
0

Если у меня есть таблица, состоящая из двух столбцов одна для идентификатора пользователя, а другая для отпечатка пальца (посещаемость, отпуск), как обнаружить всех пользователей, чье (оставить время) в на следующий день их первого отпечатка пальца?Как запросить две связанные транзакции в разные дни

USERID CHECKTIME 
2982 2015-03-11 09:08:10.000 
2982 2015-03-11 20:13:57.000 
2982 2015-03-12 08:43:35.000 
2982 2015-03-13 04:54:57.000 
2982 2015-03-13 05:01:03.000 
2982 2015-03-13 19:24:11.000 
2982 2015-03-14 10:28:26.000 
2982 2015-03-15 04:55:03.000 
2982 2015-03-15 05:01:24.000 

Пример: этот пользователь имеет чек 2015-03-12 в 08:43:35.000 и проверка его в следующий день 2015-03-13 в 04:54:57.000

я хочу запросить все пользователь, которые имеют случаи, как, что с учетом пользователя может имеют более двух регистраций в тот же день, поэтому я хочу только первый и (последний на следующий день)

+1

Но почему вы не храните его, если его регистрация или выход? Более или менее невозможно узнать, что это такое, если это 1000 или строк. (И, возможно, одного не хватает, потому что человек однажды прокрался в/из.) – jarlh

+0

@just_name, пожалуйста, не стесняйтесь подавать обратную ссылку на [ниже ответа] (http://stackoverflow.com/a/29511717/3208640) – jfun

+0

@just_name, извините, была небольшая проблема с предыдущим ответом, который был изменен, я просто хотел сообщить вам, что эта версия завершена. удачи. – jfun

ответ

1

Предполагая, что все пользователи правильно проверяют и нет пропущенного контрольного времени.

не Предположим, наша схема является:

create table tblchk (USERID int, CHECKTIME datetime) 
insert into tblchk values 
(2982 ,'2015-03-11 09:08:10.000'), 
(2982 ,'2015-03-11 20:13:57.000'), 
(2982 ,'2015-03-12 08:43:35.000'), 
(2982 ,'2015-03-13 04:54:57.000'), 
(2982 ,'2015-03-13 05:01:03.000'), 
(2982 ,'2015-03-13 19:24:11.000'), 
(2982 ,'2015-03-14 10:28:26.000'), 
(2982 ,'2015-03-15 04:55:03.000'), 
(2982 ,'2015-03-15 05:01:24.000'); 

Нет, мы можем использовать row number, чтобы определить, какие записи для enter time и который exit time, ODD s являются въезжать и Even s являются выход:

select userid, 
     checktime, 
     case row_number()over(partition by userid order by checktime)%2 
      when 1 then 'Enter' 
      else 'Exit' 
     end [type] 
from tblchk 

результат:

userid checktime    type 
2982 2015-03-11 09:08:10.000 Enter 
2982 2015-03-11 20:13:57.000 Exit 
2982 2015-03-12 08:43:35.000 Enter 
2982 2015-03-13 04:54:57.000 Exit 
2982 2015-03-13 05:01:03.000 Enter 
2982 2015-03-13 19:24:11.000 Exit 
2982 2015-03-14 10:28:26.000 Enter 
2982 2015-03-15 04:55:03.000 Exit 
2982 2015-03-15 05:01:24.000 Enter 

Теперь, если мы хотим, чтобы указать дни с последним checktime является enter и первого checktime следующего дня exit мы можем использовать выше запрос как:

with cte as 
(
    select userid, 
      checktime, 
      row_number()over(partition by userid order by checktime) rn 
    from tblchk 
) 

select q_enter.userid as [USER], 
     q_enter.checktime as EnterTime, 
     q_exit.checktime as ExitTime 
from 
(
    select userid, 
      max(checktime) checktime, 
      max(rn) rn 
    from cte 
    group by userid,cast(checktime as date) 
    having max(rn)%2=1 
)q_enter 
join 
(
    select userid, 
      min(checktime) checktime, 
      min(rn) rn 
    from cte 
    group by userid,cast(checktime as date) 
    having min(rn)%2=0 
)q_exit 
on q_enter.userid=q_exit.userid and q_enter.rn=q_exit.rn-1 

Результат:

USER EnterTime    ExitTime 
2982 2015-03-12 08:43:35.000 2015-03-13 04:54:57.000 
2982 2015-03-14 10:28:26.000 2015-03-15 04:55:03.000 
0

Вы можете использовать агрегированные функции, такие как min и max, которые дают первый и последний

вы можете проверить здесь http://sqlfiddle.com/#!9/68897/2

ВЫБРАТЬ USERID, MIN (CHECKTIME), MAX (CHECKTIME) FROM attendence GROUP BY USERID;