我可以使用DATEDIFF来查找一组日期之间的差异,例如
DATEDIFF(MINUTE, @startdate, @enddate)
但是如何找到多组日期之间的总时间间隔?我不知道我会有多少套(停止和开始)。
数据位于多行,包含开始和停止。
ID TimeStamp StartOrStop TimeCode
----------------------------------------------------------------
1 2017-01-01 07:00:00 Start 1
2 2017-01-01 08:15:00 Stop 2
3 2017-01-01 10:00:00 Start 1
4 2017-01-01 11:00:00 Stop 2
5 2017-01-01 10:30:00 Start 1
6 2017-01-01 12:00:00 Stop 2
答案 0 :(得分:1)
此代码可以正常运行,假设您的表只存储来自一个人的数据,并且它们应该是“开始/停止/开始/停止”命令
Query.SQL.Add ('select "Costumer"."Name", ');
Query.SQL.Add ( '"Costumer"."Age", ',);
Query.SQL.Add ( '"Costumer"."Gender" ');
Query.SQL.Add ( 'from "Costumer" ');
Query.SQL.Add ( 'where "Costumer"."Name" = :aCostumerName');
答案 1 :(得分:1)
如果你的开始和停止是可靠的,这将有效。您的样品有两个开始 - 10:00和10:30开始。我假设在生产中你将有一个员工ID分组,所以我把它添加到样本数据代替标识列。
同样在生产中,CTE集将通过使用日期参数来减少。如果有隔夜轮班,您希望stops
CTE在检索结束日期时使用dateadd(day, 1, @startDate)
作为您的上限。
设置示例:
declare @temp table (
EmpId int,
TimeStamp datetime,
StartOrStop varchar(55),
TimeCode int
);
insert into @temp
values
(1, '2017-01-01 07:00:00', 'Start', 1),
(1, '2017-01-01 08:15:00', 'Stop', 2),
(1, '2017-01-01 10:00:00', 'Start', 1),
(1, '2017-01-01 11:00:00', 'Stop', 2),
(2, '2017-01-01 10:30:00', 'Start', 1),
(2, '2017-01-01 12:00:00', 'Stop', 2)
<强>查询:强>
;with starts as (
select t.EmpId,
t.TimeStamp as StartTime,
row_number() over (partition by t.EmpId order by t.TimeStamp asc) as rn
from @temp t
where Timecode = 1 --Start time code?
),
stops as (
select t.EmpId,
t.TimeStamp as EndTime,
row_number() over (partition by t.EmpId order by t.TimeStamp asc) as rn
from @temp t
where Timecode = 2 --Stop time code?
)
select cast(min(sub.StartTime) as date) as WorkDay,
sub.EmpId as Employee,
min(sub.StartTime) as ClockIn,
min(sub.EndTime) as ClockOut,
sum(sub.MinutesWorked) as MinutesWorked
from
(
select strt.EmpId,
strt.StartTime,
stp.EndTime,
datediff(minute, strt.StartTime, stp.EndTime) as MinutesWorked
from starts strt
inner join stops stp
on strt.EmpId = stp.EmpId
and strt.rn = stp.rn
)sub
group by sub.EmpId
答案 2 :(得分:1)
这可以假设您的表具有增量ID
和交错开始/停止记录
--Data sample as provided
declare @temp table (
Id int,
TimeStamp datetime,
StartOrStop varchar(55),
TimeCode int
);
insert into @temp
values
(1, '2017-01-01 07:00:00', 'Start', 1),
(2, '2017-01-01 08:15:00', 'Stop', 2),
(3, '2017-01-01 10:00:00', 'Start', 1),
(4, '2017-01-01 11:00:00', 'Stop', 2),
(5, '2017-01-01 10:30:00', 'Start', 1),
(6, '2017-01-01 12:00:00', 'Stop', 2)
--let's see every pair start/stop and discard stop/start
select start.timestamp start, stop.timestamp stop,
datediff(mi,start.timestamp,stop.timestamp) minutes
from @temp start inner join @temp stop
on start.id+1= stop.id and start.timecode=1
--Sum all for required result
select sum(datediff(mi,start.timestamp,stop.timestamp) ) totalMinutes
from @temp start inner join @temp stop
on start.id+1= stop.id and start.timecode=1
结果
+-------------------------+-------------------------+---------+
| start | stop | minutes |
+-------------------------+-------------------------+---------+
| 2017-01-01 07:00:00.000 | 2017-01-01 08:15:00.000 | 75 |
| 2017-01-01 10:00:00.000 | 2017-01-01 11:00:00.000 | 60 |
| 2017-01-01 10:30:00.000 | 2017-01-01 12:00:00.000 | 90 |
+-------------------------+-------------------------+---------+
+--------------+
| totalMinutes |
+--------------+
| 225 |
+--------------+
也许棘手的部分是join
子句。我们需要通过延迟1 @table
加入ID
。这是on start.id+1= stop.id
开展工作的地方。
另一方面,为了排除停止/开始夫妇,我们使用start.timecode=1
。如果我们没有包含此信息的列,则stop.id%2=0
之类的工作正常。