根据startdate和enddate列计算并发记录

时间:2015-02-19 19:01:03

标签: sql sql-server tsql aggregate-functions sql-date-functions

表格结构:

StaffingRecords

  • PersonnelId int
  • GroupId int
  • StaffingStartDateTime datetime
  • StaffingEndDateTime datetime

如果员工所属的日期和群组ID,当前员工的人数在当天的任何时间都低于阈值(例如3),我如何获得人员配置记录列表?

我的大脑工作的方式,我会在每天的每一分钟反复调用存储过程,但当然这会非常低效:

SELECT COUNT(PersonnelId) 
FROM DailyRosters 
WHERE GroupId=@GroupId 
    AND StaffingStartTime <= @TimeParam 
    AND StaffingEndTime > @TimeParam 
    AND COUNT(GroupId) < 3
GROUP BY GroupId
HAVING COUNT(PersonnelId) < 3

编辑:如果有助于完善问题,员工可以全天出入。例如,人员可能有0800 - 0815的人员记录,而另一个人员的记录可能是1000 - 1045。

2 个答案:

答案 0 :(得分:1)

这是一个解决方案,我找到所有不同的开始和结束时间,然后查询以查看当时有多少其他人进入。每当答案小于4时,你知道你当时人手不足,大概是在NEXT开始时间之前。

with meaningfulDtms(meaningfulTime, timeType, group_id)
as
(  
    select distinct StaffingStartTime , 'start' as timeType, group_id
    from DailyRosters 
    union
    select distinct StaffingEndTime , 'end' as timeType, group_id
    from DailyRosters 
)

select COUNT(*), meaningfulDtms.group_id, meaningfulDtms.meaningfulTime
from DailyRosters  dr
inner join meaningfulDtms on dr.group_id = meaningfulDtms.group_id
and (
 (dr.StaffingStartTime  < meaningfulDtms.meaningfulTime
     and dr.StaffingEndTime  >= meaningfulDtms.meaningfulTime
     and meaningfulDtms.timeType = 'start')
 OR
 (dr.StaffingStartTime  <= meaningfulDtms.meaningfulTime
     and dr.StaffingEndTime  > meaningfulDtms.meaningfulTime
     and meaningfulDtms.timeType = 'end')
)
group by meaningfulDtms.group_id, meaningfulDtms.meaningfulTime
having COUNT(*) < 4

答案 1 :(得分:0)

创建一个包含当天所有会议记录的表格,其中dt为PK
它将有1440行

这不会给你数零 - 没有工作人员

select allMiuntes.dt, worktime.grpID, count(distinct(worktime.personID))
  from allMinutes 
  join worktime 
    on allMiuntes.dt > worktime.start 
   and allMiuntes.dt < worktime.end 
 group by allMiuntes.dt, worktime.grpID 
having count(distinct(worktime.personID)) < 3

对于零的时间我认为最好的方法是grpID的主人 但我不确定这一个

select allMiuntes.dt, grpMaster.grpID, count(distinct(worktime.personID))
  from grpMaster
 cross join allMinutes 
  left join worktime 
    on allMiuntes.dt > worktime.start 
   and allMiuntes.dt < worktime.end 
   and worktime.grpID = grpMaster.grpID 
 group by allMiuntes.dt, grpMaster.grpID
having count(distinct(worktime.personID)) < 3