I think this might work for you:
declare @startdt datetime=cast('2016-06-01' as datetime);
declare @enddt datetime=cast('2016-07-01' as datetime);
with cte
as (select logid
,userid
,checktime
,checktype
,sensorid
,row_number() over(partition by userid
,cast(checktime as date)
order by checktype
,checktime
)
as rn1
,row_number() over(partition by userid
,cast(checktime as date)
order by checktype desc
,checktime desc
)
as rn2
from checkinout
where checktime>=@startdt
and checktime <@enddt
and checktype in ('I','O')
)
select a.logid
,a.userid
,a.checktime as punchin
,b.checktime as punchout
,a.sensorid as punchinsensor
,b.sensorid as punchoutsensor
,datediff(minute,a.checktime,b.checktime) as workminute
,case
when datepart(hour,b.checktime)*60
+datepart(minute,b.checktime)
>=(18*60+30) /* time 18:30 */
then datepart(hour,b.checktime)*60
+datepart(minute,b.checktime)
-(17*60+30) /* time 17:30 */
else 0
end as overtimeminute
from cte as a
left outer join cte as b
on b.userid=a.userid
and cast(b.checktime as date)=cast(a.checktime as date)
and b.checktype='O'
and b.rn=1
where a.checktype='I'
and a.rn1=1
;