2016-04-04 12 views
0

会社の方針のために、私が実際に使っている質問はできませんが、内訳と一般的な考えがあります。従業員が勤務しているかどうか、従業員がどこで働いているかを記録した出席登録があります。私はこれと、従業員が5シフトしたその日との間にこれを要約するようにしています。私が座っている問題は、特定の従業員が職場Aで2日間働いてから職場Bに移されたことです。職場Bで数日後、従業員は職場Aに戻ります。出席要約レポート

私の結果私の試みは、従業員が1月1日から職場Aで働き始め、2月10日に仕事シフトが2回しかないことを示しています。私は働く場所にグループを持っており、開始日と終了日は最小と最大の選択です。

SELECT att.Employee, att.Workplace, dte.BeginDate, dte.EndDate, shf.WorkShift FROM 
(SELECT * FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan') att 
CROSS APPLY (SELECT COUNT(Shift) WorkShift FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan' AND Employee = att.Employee AND WorkPlace = att.WorkPlace AND Shift = 'Worked') shf 
CROSS APPLY (SELECT MAX(WorkDate) BeginDate, MIN(WorkDate) EndDate FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan' AND Employee = att.Employee AND WorkPlace = att.WorkPlace) dte 

ので、レコードは次のように表示されます。この従業員

(私は非常に悪いグリッドの申し訳ありませんが、私はそれはかなり見えるようにする方法がわからない、あなたはそれが良く見えるように編集することが歓迎以上のもの)
| Name | Workplace | beginDate | endDate | WorkShift | 
| Jane | WorkPlaceA | 1-Jan  | 2-Jan | 2   | 
| Jane | WorkPlaceB | 3-Jan  | 8-Jan | 5   | 
| Jane | WorkPlaceA | 9-Jan  | 10-Jan | 2   | 

出欠表には、私はあなたがCTEのを使ってこれを実現することができると信じて、この

| Name | Workplace | Date | Shift | 
| Jane | WorkplaceA | 1-Jan | Worked | 
| Jane | WorkplaceA | 2-Jan | Worked | 
| Jane | WorkplaceB | 3-Jan | Worked | 
| Jane | WorkplaceB | 4-Jan | Worked | 
| Jane | WorkplaceB | 5-Jan | Worked | 
| Jane | WorkplaceA | 6-Jan | Absent | 
| Jane | WorkplaceA | 7-Jan | Absent | 
| Jane | WorkplaceA | 8-Jan | Worked | 
| Jane | WorkplaceB | 9-Jan | Worked | 
| Jane | WorkplaceB | 10-Jan | Worked | 
+0

@Tannerをカウントしていない、私はそのようにすぐに私は再びそれを超える読み始めとして欠けていたが実現しました。 –

答えて

1

ようになります。期待値を示すサンプルコードです。

;WITH CTE1 AS (
SELECT Employee, WorkPlace, TransactionDate, 
    ROW_NUMBER() OVER(PARTITION BY WorkPlace ORDER BY TransactionDate) AS WP, 
    ROW_NUMBER() OVER(ORDER BY TransactionDate) AS RN FROM Attendance WHERE Shift = 'Worked'), 
    CTE2 AS (SELECT Employee, WorkPlace, TransactionDate, WP, RN, WP-RN AS GB FROM CTE1), 
    CTE3 AS (SELECT Employee, WorkPlace, MIN(TransactionDate) AS TransactionDate, COUNT(1) AS Shifts FROM CTE2 GROUP BY Employee, WorkPlace, GB) 

SELECT Employee, WorkPlace, TransactionDate AS [Start Date], DATEADD(DAY,Shifts - 1,TransactionDate) AS [End Date], Shifts FROM CTE3 ORDER BY TransactionDate ASC 
+0

これはほぼ100%働いていますが、問題は従業員が勤務シフトから不在シフトに移行したときです。終了日は、最初の休止時に停止します。それを回避する方法。 –

+0

これは最終的な解決策ではありませんが、私が必要としていたものを手に入れていたのですが、正しい解決策に役立ちました。そして、これは私の質問に答えました。ありがとう@ランドルフ –

0

あなたの出力が間違っていると思います。

私はあなたがテーブルを埋める方法が間違っていると思います。

私のクエリを確認し、それがさらにoptmizeすることができ、それが不在の日に、私は今、編集を行った

declare @t table(Name varchar(100),Workplace varchar(100), AttnDate date ,Shifts varchar(100)) 
insert into @t values 
('Jane','WorkplaceA',' 1-Jan-16','Worked') 
,('Jane','WorkplaceA',' 2-Jan-16','Worked') 
,('Jane','WorkplaceB',' 3-Jan-16','Worked') 
,('Jane','WorkplaceB',' 4-Jan-16','Worked') 
,('Jane','WorkplaceB',' 5-Jan-16','Worked') 
,('Jane','WorkplaceA',' 6-Jan-16','Absent') 
,('Jane','WorkplaceA',' 7-Jan-16','Absent') 
,('Jane','WorkplaceA',' 8-Jan-16','Worked') 
,('Jane','WorkplaceB',' 9-Jan-16','Worked') 
,('Jane','WorkplaceB','10-Jan-16','Worked') 

DECLARE @Name VARCHAR(100) = 'Jane' 
DECLARE @FromDate DATE = '01-Jan-16' 
DECLARE @ToDate DATE = '31-Jan-16'; 

WITH CTE 
AS (
    SELECT * 
     ,row_number() OVER (
      ORDER BY attndate 
      ) rn 
    FROM @t 
    WHERE NAME = @Name 
     AND (
      AttnDate BETWEEN @FromDate 
       AND @ToDate 
      ) 
    ) 
    ,CTE1 
AS (
    SELECT A.NAME 
     ,A.workplace 
     ,A.AttnDate 
     ,Shifts 
     ,rn 
     ,1 RN1 
    FROM cte A 
    WHERE rn = 1 

    UNION ALL 

    SELECT a.NAME 
     ,a.workplace 
     ,a.AttnDate 
     ,a.Shifts 
     ,CASE 
      WHEN a.workplace = b.workplace 
       THEN b.rn 
      ELSE b.rn + 1 
      END rn 
     ,RN1 + 1 
    FROM CTE A 
    INNER JOIN CTE1 b ON a.attndate > b.attndate 
    WHERE a.rn = RN1 + 1 
    ) 
    ,CTE2 
AS (
    SELECT NAME 
     ,Workplace 
     ,AttnDate beginDate 
     ,(
      SELECT max(AttnDate) 
      FROM CTE1 b 
      WHERE b.rn = a.rn 
      ) endDate 
     ,(
      SELECT count(*) 
      FROM CTE1 b 
      WHERE b.rn = a.rn 
       AND Shifts = 'Worked' 
      ) WorkShift 
     ,rn 
     ,ROW_NUMBER() OVER (
      PARTITION BY rn ORDER BY rn 
      ) rn3 
    FROM cte1 a 
    ) 
SELECT NAME 
    ,workplace 
    ,beginDate 
    ,endDate 
    ,WorkShift 
FROM cte2 
WHERE rn3 = 1 
関連する問題