MSSQL 2016
目前我有以下表格:
https://i.stack.imgur.com/W4GX6.png
OwnerName = Jan今天工作时间为07.00至15:30。这意味着他的总工作时间应为8.5小时。然而,当我总结分钟时,由于他有重叠的活动,我得到了更多。我怎样才能排除这些重叠的活动并计算他在这一天的总工作时间: 2017年9月12日
现在,此表不仅包含2017-09-12的数据,而且每天都有计划的活动。所以查询应该考虑到这一点。此外,该表中有多个所有者,即Luc。这也是查询应该处理的问题。
有人能帮助我吗? :)
编辑:让事情更清楚。结果应采用以下格式
|------------------------|------------------|----------------|
| Ownername | Date | Time in hours |
|------------------------|------------------|----------------|
| Jan | 2017-09-12 | 8.5 |
| Luc | 2017-09-12 | 8.5 |
| John | 2017-09-12 | 8.5 |
| Doe | 2017-09-11 | 7 |
| Jan | 2017-09-13 | 4 |
| Doe | 2017-09-14 | 8.5 |
| Tom | 2017-09-14 | 7 |
我目前的猜测是我首先必须确定哪些活动是重叠的。我想我必须使用BETWEEN语句来做到这一点。然后使用CASE语句将此时间添加到当天的总时间(小时)。
答案 0 :(得分:0)
我认为您的问题是使用SUM关键字。而是尝试使用DATEDIFF。 这将是准确的,如果你每天有多个记录使用CURSOR,那么你可以独立地获取evry记录。
例如,在CURSOR中使用DATEDIFF,然后使用该结果
答案 1 :(得分:0)
好的,请尝试以下解决方案。它删除了其他一些包含的间隔,然后使用LAG
窗口函数访问上一行并更新间隔以使其不重叠。然后我们可以简单地执行SUM
。
WITH
inputs ( name, date_fr, date_to ) AS (
select 'Dan' , cast('07-Jun-17 08:00:00' as DATETIME), cast('07-Jun-17 10:00:00' as DATETIME) union all
select 'Dan' , cast('07-Jun-17 11:00:00' as DATETIME), cast('07-Jun-17 12:00:00' as DATETIME) union all
select 'Jan' , cast('08-Jun-17 08:15:00' as DATETIME), cast('08-Jun-17 15:00:00' as DATETIME) union all
select 'Jan' , cast('08-Jun-17 08:15:00' as DATETIME), cast('08-Jun-17 10:00:00' as DATETIME) union all
select 'Jan' , cast('07-Jun-17 08:30:00' as DATETIME), cast('07-Jun-17 15:00:00' as DATETIME) union all
select 'Jan' , cast('07-Jun-17 09:00:00' as DATETIME), cast('07-Jun-17 9:30:00' as DATETIME) union all
select 'Jan' , cast('07-Jun-17 08:00:00' as DATETIME), cast('07-Jun-17 10:00:00' as DATETIME)
)
-- End of simulated input (for testing only, not part of the solution).
SELECT name, year(date_fr) year, month(date_fr) month, day(date_fr) day,
sum(cast(datediff(minute, date_fr, date_to) as decimal(10,4)))/60
FROM
(
SELECT t.name,
CASE WHEN lag(date_to) over (partition by name order by date_fr) > date_fr
THEN lag(date_to) over (partition by name order by date_fr)
ELSE date_fr
END date_fr,
t.date_to
FROM
(
SELECT name, date_fr, date_to
FROM inputs i1
WHERE NOT EXISTS (SELECT 1 FROm inputs i2 WHERE i1.name = i2.name and i2.date_fr < i1.date_fr and i2.date_to > i1.date_to) -- this removes fully nested intervals
) t
) tt
WHERE tt.date_fr < tt.date_to
GROUP BY name, year(date_fr), month(date_fr), day(date_fr)