如何查询不同日期的两笔关联交易
How to query the two related transactions in different days
如果我有table由两列组成,一列是用户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
示例:此用户在 08:43:35.000
签到 2015-03-12
并在第二天 2015-03-13
在 04:54:57.000
退房
我想查询所有遇到这种情况的用户,考虑到用户可能在同一天签入两次以上,所以我只想要第一个和(第二天的最后一个)
您可以使用 min 和 max 等聚合函数,它们给出先进后出值
你可以在这里查看
http://sqlfiddle.com/#!9/68897/2
SELECT USERID,MIN(CHECKTIME),MAX(CHECKTIME) FROM attendance GROUP BY USERID;
假设所有用户都正确检查并且没有错过检查时间。
假设我们的架构是:
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 是 enter,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
现在如果我们想指定最后一次检查时间是 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
如果我有table由两列组成,一列是用户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
示例:此用户在 08:43:35.000
签到 2015-03-12
并在第二天 2015-03-13
在 04:54:57.000
我想查询所有遇到这种情况的用户,考虑到用户可能在同一天签入两次以上,所以我只想要第一个和(第二天的最后一个)
您可以使用 min 和 max 等聚合函数,它们给出先进后出值
你可以在这里查看 http://sqlfiddle.com/#!9/68897/2
SELECT USERID,MIN(CHECKTIME),MAX(CHECKTIME) FROM attendance GROUP BY USERID;
假设所有用户都正确检查并且没有错过检查时间。
假设我们的架构是:
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 是 enter,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
现在如果我们想指定最后一次检查时间是 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