MSSQL选择在一个日期范围内满足条件的计数

时间:2012-04-24 09:53:36

标签: sql sql-server

我有一个包含dateemployeeID(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天内的所有夜班。

3 个答案:

答案 0 :(得分: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

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

答案 2 :(得分: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]