【问题标题】:How to query the two related transactions in different days如何查询不同日期的两笔相关交易
【发布时间】:2015-04-08 09:36:29
【问题描述】:

如果我的表格由两列组成,一列用于用户 ID,另一列用于指纹(出席,离开)如何检测所有用户(离开时间)在他们的第一个指纹的第二天?

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-1304:54:57.000

我想查询所有有类似情况的用户,考虑到用户可能在同一天有两个以上的签出,所以我只想要第一个和(第二天的最后一个)

【问题讨论】:

  • 但是你为什么不存储它的签入或签出呢?如果它是 1000 或行,它或多或少不可能知道它是什么。 (也许一个人不见了,因为这个人确实偷偷溜进/溜出一次。)
  • @just_name 请随时在below answer提供反馈
  • @just_name,抱歉,之前修改的答案有一个小问题,我只是想通知您此版本已完成。祝你好运。

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


【解决方案1】:

假设所有用户都正确检查并且没有错过检查时间。

假设我们的 Schema 是:

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 timeODDs 是进入,Evens 是退出:

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

【讨论】:

    【解决方案2】:

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

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

    SELECT USERID,MIN(CHECKTIME),MAX(CHECKTIME) FROMattence GROUP BY USERID;

    【讨论】:

      猜你喜欢
      • 2019-08-02
      • 1970-01-01
      • 2018-10-10
      • 2017-11-22
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 2022-08-22
      相关资源
      最近更新 更多