2

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

我有一个带有日期/时间戳的劳动力交易表,供用户打卡和打卡。每个事务(行)都有一个用户名、开始和停止时间、总小时数和一个“标签”(通常是工单#)。

对于假期,我们为每个用户添加一个没有开始或停止时间的事务,总小时数为 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

这就是问题所在。如果用户在关键字为 BUSINESS days 之前的 2 个工作日工作,则该用户仅应获得 8 小时的假期。休假日(带有 VACATION 标签)将被视为“工作”。因此,基本上,如果前 2 天的每一天都有任何劳务交易,他们就有资格享受假期。

更复杂的是,周一到周五将是一个典型的工作周,但是,人们可以在周六工作(尽管不是必需的),所以如果周一放假,他们可以在周四/周五或周五/周六工作有资格享受假期。

该报告将每周(周一)运行一次,并查看前一周。所以我的思考过程是你寻找任何带有假日标签的交易,然后在 2 个“工作日”前检查每天的任何交易。如果一天或两天没有找到交易,则返回用户或完整的假期行,以表明他们不符合条件(最终结果集应该是不符合假期条件的交易或用户的列表)。

对于检查前 2 天或确定“工作日”(可能包括星期六)的任何和所有帮助将不胜感激!如果您需要任何进一步的细节,也请告诉我。

谢谢!

4

2 回答 2

0

这种逻辑很难以可读和高性能的方式在 sql 中表达。通常,我发现创建一个事实表更容易,因为数据太少了。这样,您就可以加入这个事实表。我不知道你的表叫什么,所以我就叫它“日志”。

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

更新

为了考虑到允许周五/周六而不是周四/周六的限制,我修改了事实表以包含允许的组合。对于每个有效组合,给出一个新的工作日(假日)行和两个允许的偏移量。对于周一(美国的工作日 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
于 2012-11-20T21:02:27.157 回答
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 天的标签(按日期):

开始日期 开始标签 前 1 天 前 2 天 前 3 天 前 4 天 前 5 天
---------- --------- ------------ ------------- ------ -------- ------------- -------------
2012-07-05 WO98765 WO24680 假日 WO13579 WO12345 NULL

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

于 2012-11-20T20:40:48.723 回答