2012-11-20 3 views
2

많은 비슷한 질문을 읽었지만 특별한 경우는 내가 찾은 대부분의 다른 상황보다 조금 간단하고 복잡한 것입니다. 질문은 다음과 같습니다.SQL의 휴일 전후의 "영업일"

클럭 인 및 클로우 아웃 사용자에 대한 날짜/시간 스탬프가있는 노동 거래 테이블이 있습니다. 각 트랜잭션 (행)에는 사용자 이름, 시작 및 종료 시간, 총 시간 수 및 "태그"(일반적으로 작업 주문 번호)가 있습니다.

공휴일의 경우 시작 또는 종료 시간이없는 총 사용자 수에 대해 8 시간을 합계 시간으로, "휴가"를 태그로 추가합니다. 아래 표의 샘플을 작성했습니다.

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 일보다 2 영업일 앞선 경우에만 8 시간의 휴가를 제공해야합니다. 휴일 (VACATION이라는 태그가 있음)은 "근무 중"으로 간주됩니다. 그래서 기본적으로 2 일 전에 각각의 노동 거래가 있다면 휴가 자격이됩니다.

월요일부터 금요일까지는 월요일부터 금요일까지 일하는 것이 일반적이지만, 필수 사항은 아니지만 토요일에 일할 수있는 사람들이 많기 때문에 월요일이 휴일 인 경우에도 목요일/금 또는 금/토 휴일에 대한 자격.

이 보고서는 일주일에 한 번 (월요일에) 실행되고 이전 주를 볼 것입니다. 따라서 내 생각으로는 Holiday의 태그가있는 거래를 찾는다는 것입니다. 하루 중 어떤 거래보다 먼저 "영업일 기준 2 일"전에 확인하십시오. 한 일 또는 두 일 동안 거래가 발견되지 않으면 사용자 또는 전체 휴일 행을 반환하여 자격이 없음을 나타냅니다 (최종 결과 집합은 거래 목록 또는 휴가 자격이없는 사용자 여야 함).

2 일 전 확인 또는 "업무 일"(토요일 포함) 결정에 도움이되는 모든 도움을 주시면 대단히 감사하겠습니다! 또한 세부 정보가 필요한 경우 알려 주시기 바랍니다.

감사합니다.

+0

그래서 자체에 테이블을 조인하고, 단지'DATEPART (평일, STARTDATE를)'쿼리? – Kermit

+0

목요일, 토요일에 근무하는 사람은 월 휴가 자격이 있습니까? – dbenham

+0

@dbenham - 목/토가 유효하지 않습니다. 목/금 또는 금/토 전용. 금요일은 토요일이 아닙니다. 화요일에 휴일 인 경우, 유효한 경우는 금/월 또는 토/월 –

답변

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

.

+0

이전 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