如何查询不同日期的两个相关交易

时间:2015-04-08 09:36:30

标签: sql sql-server datetime time sql-server-2012

如果我的表包含两列,一列用于用户ID,另一列用于指纹(出勤,请假)如何检测第一个指纹第二天(离开时间)的所有用户? / p>

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

我想查询所有有类似案例的用户,考虑到用户可能在同一天有两个以上的登记入住,所以我只想要第一个和(第二天的最后一个)

2 个答案:

答案 0 :(得分: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 timeODD是输入,Even是退出:

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

现在,如果我们要指定上次检查时间为enter且第二天的第一个检查时间为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

答案 1 :(得分:0)

您可以使用min和max之类的聚合函数,它们给出了前进和后出值

你可以在这里查看 http://sqlfiddle.com/#!9/68897/2

SELECT USERID,MIN(CHECKTIME),MAX(CHECKTIME)来自关注GROUP BY USERID;