当前位置: 代码迷 >> Sql Server >> 请问单纯刷卡记录转换签到签退行转列方法
  详细解决方案

请问单纯刷卡记录转换签到签退行转列方法

热度:159   发布时间:2016-04-24 08:45:20.0
请教单纯刷卡记录转换签到签退行转列方法
打卡表只有个单纯的某岗位、某卡号和刷卡时间的记录。现要根据岗位和卡号自动识别签到签退。
规则为:
某天、某卡号在某岗位第一次刷卡识别为签到,第二次识别为签退。一日可多次签到、签退,总之奇数次为签到,偶数次为签退。
如打卡表:
岗位 卡号                    刷卡时间
07 103  2015-11-10 11:07:04.000
07 103 2015-11-10 11:22:44.000
07 104 2015-11-10 11:07:31.000
07 104 2015-11-10 11:23:02.000
09 110 2015-11-11 08:57:09.000
09 110 2015-11-12 08:55:58.000
09 110 2015-11-12 09:00:22.000
09 110 2015-11-12 10:00:35.000

转换为:
岗位 卡号 签到时间                  签退时间
07 103 2015-11-10 11:07:04.000   2015-11-10 11:22:44.000
07 104 2015-11-10 11:07:31.000   2015-11-10 11:23:02.000
09 110 2015-11-11 08:57:09.000
09 110 2015-11-12 08:55:58.000   2015-11-12 09:00:22.000
09 110 2015-11-12 10:00:35.000

菜鸟刚半条腿入门sql,请教大神指点!
------解决思路----------------------
with T(pos,num,tim) as
(select '07', '103',  '2015-11-10 11:07:04.000' union all select 
 '07', '103', '2015-11-10 11:22:44.000' union all select 
 '07', '104', '2015-11-10 11:07:31.000' union all select 
 '07', '104', '2015-11-10 11:23:02.000' union all select 
 '09', '110','2015-11-11 08:57:09.000' union all select 
 '09', '110', '2015-11-12 08:55:58.000' union all select 
 '09', '110', '2015-11-12 09:00:22.000' union all select 
 '09', '110', '2015-11-12 10:00:35.000'),
 T1 as (select *,rn=ROW_NUMBER() over (partition by pos,num,convert(varchar(10),tim,120) order by tim) from T),
 T2 as (select * from T1 where rn%2=1),
 T3 as (select * from T1 where rn%2=0)
 
select T2.pos as 岗位,T2.num as 卡号,T2.tim as 签到时间,T3.tim as  签退时间 
from T2 left join T3 on t2.pos=t3.pos and t2.num=t3.num and convert(varchar(10),t2.tim,120)=convert(varchar(10),t3.tim,120) and t2.rn+1=t3.rn
------解决思路----------------------

CREATE TABLE #T_A(  
    岗位 varchar(10)  
    , 卡号 varchar(10)  
    ,  刷卡时间 varchar(30)  
)   
INSERT INTO #T_A  
SELECT '07','103','2015-11-10 11:07:04.000'  
UNION  ALL
SELECT '07','103','2015-11-10 11:22:44.000'  
UNION  ALL
SELECT '07','104','2015-11-10 11:07:31.000'  
UNION  ALL
SELECT '07','104','2015-11-10 11:23:02.000'  
UNION  ALL
SELECT '09','110','2015-11-11 08:57:09.000'  
UNION  ALL
SELECT '09','110','2015-11-12 08:55:58.000'  
UNION  ALL
SELECT '09','110','2015-11-12 09:00:22.000'  
UNION  ALL
SELECT '09','110','2015-11-12 10:00:35.000'  

--select * from #T_A

select * ,ROW_NUMBER() OVER(PARTITION BY 岗位,卡号,left(刷卡时间,10) ORDER BY 刷卡时间) as rn into #aa from #T_A
--select * from #aa
select a.岗位,a.卡号,a.刷卡时间 as '签到时间',isnull(b.刷卡时间,'') as '签退时间'
from
(
select 岗位,卡号,刷卡时间,rn from #aa where rn%2<>0
) a left join 
(
select 岗位,卡号,刷卡时间,rn from #aa where rn%2=0
) b on a.岗位=b.岗位 and a.卡号=b.卡号 and left(a.刷卡时间,10)=left(b.刷卡时间,10)
and b.rn-a.rn=1
drop table #aa
drop table #T_A

/*
(8 行受影响)

(8 行受影响)
岗位         卡号         签到时间                           签退时间
---------- ---------- ------------------------------ ------------------------------
07         103        2015-11-10 11:07:04.000        2015-11-10 11:22:44.000
07         104        2015-11-10 11:07:31.000        2015-11-10 11:23:02.000
09         110        2015-11-11 08:57:09.000        
09         110        2015-11-12 08:55:58.000        2015-11-12 09:00:22.000
09         110        2015-11-12 10:00:35.000        

(5 行受影响)
*/
  相关解决方案