9:20到16:30之间的时间检查,并在当天21:00到下一个日期的凌晨3:00之间检查,这是表格
select *
from checkinout
输出:
USERID CHECKTIME
-----------------------------------------
64 2018-03-02 13:04:26.000
64 2018-03-03 01:11:38.000
64 2018-03-03 13:14:01.000
64 2018-03-04 01:44:10.000
64 2018-03-04 13:29:40.000
用户ID 64在2018-03-02 13:04:26.000办理登机手续,并在第二天2018-03-03 01:11:38.000退房,这是我需要的表格
UserID checkdate Checkin Checkout workhour
----------------------------------------------------------------------------------
64 2018-03-02 13:04:26.000 01:11:38.000 =13:04:26.000-01:11:38.000
64 2018-03-03 13:14:01.000 01:44:10.000 =13:14:01.000-01:44:10.000
如何从我的表格中获得此输出?
答案 0 :(得分:0)
你去吧
select userid, max(cast(checkin as date)) checkdate,
max(CONVERT(VARCHAR(8),checkin,108)) checkin, max(CONVERT(VARCHAR(8),checkout,108)) checkout,
max(CONVERT(VARCHAR(8),checkin,108))+'-'+max(CONVERT(VARCHAR(8),checkout,108))workhour
from
(select userid, cast(checktime as date) checkdate, checktime,
case when row_number() over(order by cast(checktime as date), checktime) % 2 = 1
then 'Checkin'
else 'Checkout' end [Action],
case when row_number() over(order by cast(checktime as date), checktime) % 2 = 1
then row_number() over(order by cast(checktime as date), checktime)
else row_number() over(order by cast(checktime as date), checktime)-1
end Visit
from #checkinout)a
pivot (min(checktime) for [action] in ([Checkin], [Checkout])) a
group by userid, visit
答案 1 :(得分:0)
我认为这会让你进入球场。这将使用您在评论中添加的有关如何识别“检入时间”和“检出时间”的信息,而不是依据按日期排序时依赖记录的顺序。
SELECT CheckIn.Userid,
Cast(CheckIn.CheckInTime as Date) as CheckDate,
CONVERT(VARCHAR(8),CheckIn.CheckInTime,108) as CheckIn,
CONVERT(VARCHAR(8),CheckOut.CheckOutTime,108) as CheckOut,
DATEDIFF(hh,CheckIn.CheckInTime, CheckOut.CheckOutTime) as hours
From
(
SELECT
ROW_NUMBER() OVER (PARTITION BY userid ORDER BY checktime) as checkid,
Checktime as CheckInTime,
Userid
From Checkinout
WHERE CAST(CheckTime as Time) BETWEEN '09:14:00' AND '16:30:00'
)CheckIn
INNER JOIN
(
SELECT
ROW_NUMBER() OVER (PARTITION BY userid ORDER BY checktime) as checkid,
CheckTime as CheckOutTime
Userid
WHERE CAST(CheckTime as Time) BETWEEN '21:00:00' AND '24:00:00'
OR CAST(CheckTime as Time) BETWEEN '00:00:00' AND '03:00:00'
From Checkinout
)CheckOut
ON CheckIn.CheckID = CheckOut.CheckId
这仍然可能有点粗略,因为我们仍然依赖CheckIn,CheckOut,CheckIn,CheckOut这样的顺序没有任何偏差,但是......再次......球场肯定。
答案 2 :(得分:0)
这是我的方法
示例数据
--sample data
if object_id('tempdb..#checkinout') is not null drop table #checkinout
CREATE TABLE #checkinout(userid int, checktime DATETIME)
INSERT INTO #checkinout(userid,checktime) VALUES
(64, '2018-03-02 13:04:26.000'),
(64, '2018-03-03 01:11:38.000'),
(64, '2018-03-03 13:14:01.000'),
(64, '2018-03-04 01:44:10.000'),
(64, '2018-03-04 13:29:40.000')
下面的查询 - 只需将#checkinout替换为您的表格,它应该可以正常工作。
--query, get some sorting in place
if object_id('tempdb..#x') is not null drop table #x
SELECT c.userid,
c.checktime,
ROW_NUMBER() OVER(PARTITION BY c.userid ORDER BY c.checktime) AS 'Sorted'
INTO #x
FROM #checkinout AS c --replace with your table, and everything should work
--label the rows by checkin or checkout
if object_id('tempdb..#y') is not null drop table #y
SELECT x.*,
CASE WHEN x.Sorted % 2 <> 0 THEN 'Checkin' ELSE 'Checkout' END AS 'Type'
INTO #y
FROM #x AS x
--get data into format desired
SELECT cin.userid,
CAST(cin.checktime AS DATE) AS 'CheckDate',
CAST(cin.checktime AS TIME) AS 'Checkin',
CAST(cout.checktime AS TIME) AS 'Checkout',
DATEDIFF(HOUR, cin.checktime, cout.checktime) AS 'Hours'
FROM #y AS cin
outer APPLY
(
SELECT y.checktime
FROM #y AS y
WHERE y.userid=cin.userid AND y.Type='Checkout' AND y.Sorted=cin.Sorted+1
) AS cout
WHERE cin.Type='Checkin' AND cout.checktime IS NOT null
输出
userid CheckDate Checkin Checkout Hours
64 2018-03-02 13:04:26.0000000 01:11:38.0000000 12
64 2018-03-03 13:14:01.0000000 01:44:10.0000000 12