1

我有一张包含date, employeeID(int) 和ShiftWorked(可以是晚上/白天/周末或晚上) 的表格。每个员工和日期组合都有一行

我想构建一个查询,让我计算在花名册期间的每个日期之前和之后的一周内有多少人上夜班。

--------------------------------------------------------------------------
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 天的所有夜班。

4

3 回答 3

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

于 2012-04-24T09:57:59.627 回答
1

以下查询将返回两列:参考(名册)日期和参考日期前 7 天到后 7 天在夜班工作的(不同)人数。

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');如果不是这种情况,则需要对日期比较进行更多调整。

于 2012-04-24T11:42:01.497 回答
0

您可以通过将 ROSTER 表连接到自身来完成它,从而为每个员工和每天创建多个结果行。否则,您的 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]
于 2012-04-24T10:26:38.833 回答