Sql server 如何划分复杂表
我在SQL Server中有一个名为Sql server 如何划分复杂表,sql-server,tsql,partitioning,Sql Server,Tsql,Partitioning,我在SQL Server中有一个名为CHECKINOUT的表,该表包含以下列: PASSID CHECKTIME CHECKTYPE UID -------------------------------------------------- PS3 2015-08-05 01:12:02.100 0 CAA0322 PS3 2015-08-06 02:17:02.310 1 CAA0322 PS4 2015-08-03
CHECKINOUT
的表,该表包含以下列:
PASSID CHECKTIME CHECKTYPE UID
--------------------------------------------------
PS3 2015-08-05 01:12:02.100 0 CAA0322
PS3 2015-08-06 02:17:02.310 1 CAA0322
PS4 2015-08-03 01:02:03.200 0 CAA0322
PS4 2015-08-03 11:11:01.233 1 CAA0322
PS3 2015-08-02 11:11:01.210 0 CAA0322
PS3 2015-08-02 12:02:04.147 1 CAA0322
PS1 2015-09-05 11:11:01.210 0 CAA0322
PS1 2015-09-05 01:12:09.010 1 CAA0322
PASSID
是每次有人访问该场所时,在允许他们进入时,他们的签入时间被注册,并且签入类型变为0时给出的通行证
CHECKTYPE=0
当他们结帐时,他们结帐的时间也会再次登记在checktime中,但这一次
checktype标志变为1
CHECKTYPE=0
现在,在一天结束时,我希望看到每个过程的报告,不管它有多少次输入和输出,如
PASSID CheckInTime CheckOutTime UID
PS1 2015-08-05 01:12:02.100 2015-08-06 02:17:02.310 CAA0322
PS3 2015-08-05 01:12:02.100 2015-08-06 02:17:02.310 CAA0322
PS3 2015-08-02 11:11:01.210 2015-08-02 12:02:04.147 CAA0322
PS4 2015-08-03 01:02:03.200 22015-08-03 11:11:01.233 CAA0322
上述结果显示假定以下情况
- CheckInTime是描述中该ID的checktype=0的第一个checktime
- CheckOutTime是描述中该ID的checktype=1的第一个checktime
declare @PassID varchar(30)='PS3';
with LastEntryData(PASSID, CHECKTIME, CHECKTYPE, GateID, UID)
as
(
select top 2
c.PASSID, c.CHECKTIME, c.CHECKTYPE, c.GateID, c.UID
from
CHECKINOUT c
where
c.PASSID = @PassID
order by
c.CHECKTIME desc
),
CheckInTime(CHECKTIME) as
(
select
i.CHECKTIME
from
LastEntryData i
where
i.CHECKTYPE = 0),
CheckOutTime(CHECKTIME) as
(
select
i.CHECKTIME
from
LastEntryData i
where
i.CHECKTYPE = 1)
select
l.PASSID, CheckInTime = i.CHECKTIME,
CheckOutTime = o.CHECKTIME, l.UID
from
LastEntryData l, CheckInTime i, CheckOutTime o
group by
l.PASSID, l.GateID, l.UID, i.CHECKTIME, o.CHECKTIME
让我们做一张桌子。(如果这样做,您将获得更多答案。)
我将做出一些有根据的猜测,因为您的示例数据与预期输出不匹配
此查询(在PostgreSQL中)返回所有签入时间
select uid, passid, checktime as time_in
from checkinout
where checktype = 0
order by uid, passid, checktime;
-在ANSI-92 SQL标准(20多年前)中,旧样式的逗号分隔表列表样式被正确的ANSI
JOIN
语法所取代,它的使用是不鼓励的分区与查询无关,它们处理物理存储。我可以通过任何方式获得上述输出,请解释GateID…它不在示例数据中,但在SQL和结果中?数据与预期输出不匹配。在数据中,PS1在2015-08-05根本没有报到。迈克·谢里尔你刚刚救了我一天。子查询是我一直在寻找的,它可以返回一个带有签入的通行证,即使那个人还没有签出
select uid, passid, checktime as time_in
from checkinout
where checktype = 0
order by uid, passid, checktime;
uid passid time_in
--
CAA0322 PS1 2015-09-05 11:11:01.21
CAA0322 PS3 2015-08-02 11:11:01.21
CAA0322 PS3 2015-08-05 01:12:02.1
CAA0322 PS4 2015-08-03 01:02:03.2
select
t1.uid, t1.passid, t1.checktime,
(select min(checktime)
from checkinout
where uid = t1.uid
and passid = t1.passid
and checktime >= t1.checktime
and checktype = 1) as time_out
from checkinout t1
where checktype = 0
order by t1.uid, t1.passid, t1.checktime;
uid passid time_in time_out
--
CAA0322 PS1 2015-09-05 11:11:01.21
CAA0322 PS3 2015-08-02 11:11:01.21 2015-08-02 12:02:04.147
CAA0322 PS3 2015-08-05 01:12:02.1 2015-08-06 02:17:02.31
CAA0322 PS4 2015-08-03 01:02:03.2 2015-08-03 11:11:01.233
with checkinout_extended as (
select uid, passid, checktime as time_in, checktype,
lead(checktime) over (partition by uid, passid order by checktime, checktype) as time_out
from checkinout
)
select uid, passid, time_in, time_out
from checkinout_extended
where checktype = 0
order by uid, passid, time_in;