2012-04-24 86 views
1

我有一个包含date,employeeID(int)和ShiftWorked(可以是night/day/weekend或evening)的表。每个员工和日期组合都有一排在一个日期范围内满足条件的MSSQL select count

我想构建一个查询,该查询给出了有多少人在名单期间的每个日期之前和之后的一周中有过多次夜班工作。

-------------------------------------------------------------------------- 
Date (yyyy-MM-dd)  | CountOfNightshifts(for 1 week either side of date) 
-------------------------------------------------------------------------- 

2012-1-1    | 8 
2012-1-2    | 12 
2012-1-3    | 11 
2012-1-4    | 6 
etc     | etc 

我希望这是明确的。我花了好几天的时间试图让这个工作,但我没有得到任何地方。

例如:

SELECT COUNT(id), [date] 
FROM ROSTER 
WHERE Shift = night AND [date] BETWEEN DATEADD(D,-7,[date]) AND DATEADD(d,7,[date]) 
GROUP by [date] 
group by [date] 

这会给我日期列表几夜的是,当日的计数 - 并非所有值夜班的前7天与日之后。

+0

请发表您已经尝试过的内容。 – 2012-04-24 09:55:41

回答

1

下面的查询将返回两列:参考(名单)日期和已经在晚上基准日后七天前筛选工作七天(不同)的人数。

SELECT tmain.date, 
(
    SELECT COUNT(DISTINCT taux.employeeId) 
    FROM roster taux 
    WHERE taux.shiftWorked = 'night' 
     AND taux.date >= DATEADD(DAY, -7, tmain.date) 
     AND taux.date <= DATEADD(DAY, 7, tmain.date) 
) AS [number_of_distinct_people_with_night_shift] 
FROM roster tmain 
ORDER BY tmain.date; 

注1:通常我更喜欢加入了子查询,但我想这个解决方案更易于阅读。注2:我假设日期值的时间分量是不相关的,并且所有的日期都有相同的时间(即'00:00:00.00');如果不是这种情况,那么在日期比较中需要做更多的调整。

1

这个怎么样?更

SELECT 
    [date] 
    ,count(*) 
FROM 
    Shifts as s 
WHERE 
    s.Date > DATEADD(day,-7,GETDATE()) 
    AND ShiftWorked = 'Night' 
GROUP BY 
    date 

http://sqlfiddle.com/#!3/e88cc/1

数据位:

http://sqlfiddle.com/#!3/b7793/2

如果你只在特定日期感兴趣,那么你可以使用:

DECLARE @target datetime 
SET @target = GETDATE() 

SELECT 
    count(*) as NightShifts 
FROM 
    Shifts as s 
WHERE 
    ShiftWorked = 'Night' 
    AND s.Date > DATEADD(day,-7,@target) 
AND s.Date < DATEADD(day,7,@target) 

http://sqlfiddle.com/#!3/b7793/20

但是如果你有另一个实际上有周期的表(例如,账单或工资日期):

DECLARE @target datetime 
SET @target = GETDATE() 

SELECT 
p.periodDate 
    ,count(*) 
FROM 
    Shifts as s 
INNER JOIN periods as p 
    ON s.date > dateadd(day,-7,p.periodDate) 
     AND s.date < dateadd(day,7,p.periodDate) 
WHERE 
    ShiftWorked = 'Night' 
GROUP BY p.periodDate 

http://sqlfiddle.com/#!3/fc54d/2

或获得)时,没有夜班后处理:

SELECT 
    p.periodDate 
    ,ISNULL(t.num,0) as nightShifts 
FROM 
    periods as p  
    LEFT OUTER JOIN (
     SELECT 
      p.periodDate 
      ,count(*) as num 
     FROM 
      Shifts as s 
      INNER JOIN periods as P 
       ON s.date > dateadd(day,-7,p.periodDate) 
       AND s.date < dateadd(day,7,p.periodDate) 
     WHERE 
      ShiftWorked = 'Night' 
     GROUP BY p.periodDate 
    ) as t 
      ON p.periodDate = t.periodDate 

http://sqlfiddle.com/#!3/fc54d/11

+0

谢谢@ gordatron的回复 - 但也许我的问题不清楚(第一次问)。我稍微修改了链接[链接](http://sqlfiddle.com/#!3/1ded6/2)。这给了我一个特定的日子 - 而不是在7天内有多少夜班日期。 – user1353276 2012-04-24 10:41:06

+0

不是100%确定你在找什么,但在那里增加了一些选项 – gordatron 2012-04-24 10:51:07

0

您可以通过加入名册把它关闭表格自身,从而为每位员工和每天创建多个结果行。否则,您的GROUP BY子句会将您所处的期间的结果行分组到原始表的日期中。

SELECT 
    r.[date], 
    COUNT(period.id) 
FROM ROSTER r 
JOIN ROSTER period 
    ON period.employeeID=r.employeeID 
    AND period.shift = night 
    AND r.[date] BETWEEN DATEADD(d,-7,period.[date]) and DATEADD(d,7,period.[date]) 
WHERE 
    r.shift = night 
GROUP BY r.[date] 
+0

谢谢你!我交换了最后的连接子句和where子句 - 但这可能只是因为我问了这个问题 – user1353276 2012-04-24 12:16:16