SQL中假期前后的“营业日”

时间:2012-11-20 20:10:12

标签: sql date reporting-services

我已经阅读了很多类似的问题,但我的具体案例比我发现的大多数其他情况更简单,更复杂。这是个问题:

我有一张人工交易表,其中包含用于计时和退出的用户的日期/时间戳。每个交易(行)都有一个用户名,开始和停止时间,总小时数和一个"标签" (通常是工作单#)。

对于假期,我们为每个用户添加一个没有开始或停止时间的交易,8作为总小时数和" HOLIDAY"作为标签。我已经制作了下表的样本:

USER   | STARTDATE | STARTTIME | STOPDATE | STOPTIME | HOURS | TAG
JSMITH | 7/2/12    | 9:00AM    | 7/2/12   | 5:00PM   | 8     | WO12345
JSMITH | 7/3/12    | 9:00AM    | 7/3/12   | 5:00PM   | 8     | WO13579
JSMITH | 7/4/12    | NULL      | 7/4/12   | NULL     | 8     | HOLIDAY
JSMITH | 7/5/12    | 9:00AM    | 7/5/12   | 5:00PM   | 8     | WO24680
JSMITH | 7/6/12    | 9:00AM    | 7/6/12   | 5:00PM   | 8     | WO98765

这是问题所在。如果用户在关键词为商业日之前的2个工作日工作,则该用户只能享受8小时的休假。休假日(可能有VACATION标签)将符合"工作"。所以基本上如果在前两天的每一天都有任何人工交易,他们就有资格度假。

为了使问题进一步复杂化,周一至周五将是一个典型的工作周,但是,人们可以在星期六工作(虽然不是必需的)所以如果假期在星期一下降,他们可以在周四/周五工作或者周五/周六有资格享受假期。

此报告每周运行一次(星期一)并查看前一周。所以我的思维过程就是你要查找带有Holiday标签的任何交易,检查2" business"每天任何交易的前几天。如果在一天或两天内未找到任何交易,则返回用户或完整假日行,以表明他们不符合条件(最终结果集应该是不符合假期的交易或用户列表)。

任何和所有帮助,无论是前2天检查还是确定"业务"天(包括可能是星期六)将非常感谢!如果您需要任何进一步的细节,也请告诉我。

谢谢!

2 个答案:

答案 0 :(得分:0)

从这开始。

SELECT a.[STARTDATE] 'Begin Date', a.[TAG] AS 'Begin Tag', 
  b.[TAG] AS '1 Day Before', c.[TAG] AS '2 Days Before',
  d.[TAG] AS '3 Days Before',  e.[TAG] AS '4 Days Before',
  f.[TAG] AS '5 Days Before'
FROM tx a
LEFT JOIN tx b ON b.[USER] = a.[USER] 
  AND b.[STARTDATE] = DATEADD (day, -1, a.[STARTDATE])
LEFT JOIN tx c ON c.[USER] = a.[USER] 
  AND c.[STARTDATE] = DATEADD (day, -2, a.[STARTDATE])
LEFT JOIN tx d ON d.[USER] = a.[USER] 
  AND d.[STARTDATE] = DATEADD (day, -3, a.[STARTDATE])
LEFT JOIN tx e ON e.[USER] = a.[USER] 
  AND e.[STARTDATE] = DATEADD (day, -4, a.[STARTDATE])
LEFT JOIN tx f ON f.[USER] = a.[USER] 
  AND f.[STARTDATE] = DATEADD (day, -5, a.[STARTDATE])
WHERE a.[STARTDATE] = '2012-07-05'

这将为您提供前5天(按日期)的标签:

Begin Date Begin Tag 1 Day Before 2 Days Before 3 Days Before 4 Days Before 5 Days Before
---------- --------- ------------ ------------- ------------- ------------- -------------
2012-07-05 WO98765   WO24680      HOLIDAY       WO13579       WO12345       NULL

然后,您将添加逻辑以检查前两天是否为非假日工作标记。

答案 1 :(得分:0)

这种逻辑很难以可读和高效的方式在sql中表达。 通常,我发现创建事实表更容易,因为数据太少。 这样,您就可以加入这个事实表。 我不知道你的桌子叫什么,所以我只称它为'Log'。

我相信这段代码会做你想要的。

<强>更新

为了允许限制星期五/星期六,而不是星期四/星期六,我修改了事实表以包括允许的组合。对于每个有效组合,给出工作日(假日)的新行和两个允许的偏移量。 对于周一(美国的工作日2),给出两对,( - 2,-3)和( - 3,-4),分别表示周五/周六和周四/周五。

新代码:

-- Create a facts table. This would maybe not be a temp table in the final solution but
-- rather a static, indexed table. 

CREATE TABLE #validdays (
   forday int,
   validday1 int, -- offset from 'forday'
   validday2 int  -- offset from 'forday'
)
-- For each weekday, give the allowed combinations of work days
INSERT INTO #validdays values (2,-2,-3)
INSERT INTO #validdays values (2,-3,-4)
INSERT INTO #validdays values (6,-1,-2)
INSERT INTO #validdays values (5,-1,-2)
INSERT INTO #validdays values (4,-1,-2)
INSERT INTO #validdays values (3,-1,-3)
INSERT INTO #validdays values (3,-1,-4)

SELECT * 
FROM Log l
WHERE 
   l.TAG = 'HOLIDAY' AND
   NOT EXISTS 
   (SELECT *
    FROM #validdays v 
    INNER JOIN Log vl ON vl.[USER] = l.[USER] AND 
                         vl.startdate = DATEADD(day, v.validday1, l.startdate) AND
                         vl.tag <> 'HOLIDAY'
    INNER JOIN Log vl2 ON vl2.[USER] = l.[USER] AND 
                          vl2.startdate = DATEADD(day, v.validday2, l.startdate) AND
                          vl2.tag <> 'HOLIDAY'
    WHERE v.forday = datepart(dw,l.startdate)
   )
   -- Any restrictions about periodicity, i.e. check that l.startdate is within last week.
drop table #validdays