2017-01-11 9 views
1

以下の問題を解決するために、使用する機能の種類や方向を理解できたら助けてください。私はスクリプトの作業の大部分を行ってきましたが、上から下に日付を定義する方法を理解しようとしています。たとえば、1行目の最初の日付を計算し、1行目の最初の日付に基づいて2行目の1行2を計算します。私が作成した前の値に基づいて値を計算する(ループ)

例テーブル:

Employee | WorkDate | #ofBreaksInWks | EndDate | StartDate 
123   1/4/2016         1/4/2016 
123   1/5/2016    
123   1/6/2016  2 
123   1/27/2016 
123   1/28/2016  5    *1/28/2016 *3/10/2016 
123   3/10/2016 
123   3/9/2016  1 
123   3/25/2016  
123   4/1/2016    
123   4/10/2016   
123   4/15/2016  4   

= Today's date *05/15/2016

= Values with asterisk* will be calculative

私は4または< 13週間働いた場合、私はどのように応じて、従業員に終了日を割り当てる必要があります私は多く働いた。私はすべてのMINで非常に最初の開始日を定義している

  1. は私が5週間の休憩があることがわかり3以上である最初のブレークを探し"1/4/2016"
  2. 日付を働きました。私は私が離陸した以上に働いたかどうかをチェックしなければならない。 WorkDateマイナスStartDate1/28/2016-3/10/2016)。 5週間を超える場合は、終了日を割り当てます(WorkDate)。
  3. 次に私は次のものに行きます。私は4週間(4/15/2016 - *05/15/2016)を見るので、私は従業員が4週間以上働いたかどうかを計算する。この場合、従業員は5週間働いています。前にStartDate3/10/2016をマイナス4/15/2016WorkDate)で計算します。

私は開始日と終了日を計算する方法を知っていますが、次の各行が前の値に依存するため、一度に1つずつ達成する方法がわかりません。助けてください!

+0

日付フィールドのデータ型は? – Shell

+0

@Shell Datetime – Stephanie

+0

データベースがこの問題の最適な解決方法であるかどうかわかりません。 SQL Serverは時系列分析用に設計されていません。理想的には、すべての行は、そのテーブルの他のユニットとは完全に独立した1ユニットのデータである必要があります。たぶん、Excelは、これらのシリーズの依存関係を処理するために設計された、より優れたツールです。 – CodeJockey

答えて

1

Temp TableとProcessedフラグを持つWhileループを使用して、必要なものを実現できます。

  IF (OBJECT_ID('tempdb..#YourTempTable') IS NOT NULL) 
      BEGIN 
       DROP TABLE #YourTempTable; 
      END 

      -- Populate Temp Table 
      SELECT 
       Processed = 0, 
       Id, 
       Employee, 
       WorkDate, 
       EndDate, 
       StartDate 
      INTO 
       #YourTempTable 
      FROM 
       DataSourceTable; 

       DECLARE @Id int = 0; 
       DECLARE @LastId int = 0; 
       DECLARE @Employee nvarchar(30) = ''; 
       DECLARE @WorkDate int = 0; 
       DECLARE @LastWorkDate int = 0; 

       WHILE EXISTS (SELECT TOP 1 Processed FROM #YourTempTable WHERE Processed = 0) 
       BEGIN 
        SELECT TOP 1 
         @Id = Id, 
         @Employee = Employee, 
         @WorkDate = WorkDate 
        FROM 
         #YourTempTable 
        WHERE 
         Processed = 0; 

        UPDATE 
         DataSourceTable 
        SET 
         NewDefinedDate = @WorkDate -- Combined with something with @LastWorkDate 
        WHERE 
         Id = @Id; 

        SET @LastId = @Id; 
        SET @LastWorkDate = @LastWorkDate; 

        UPDATE 
         #YourTempTable 
        SET 
         Processed = 1 
        WHERE 
         Id = @Id; 
       END 
      END 

      IF (OBJECT_ID('tempdb..#YourTempTable') IS NOT NULL) 
      BEGIN 
       DROP TABLE #YourTempTable; 
      END 
+1

これは素晴らしいアイデアです。私はwhileループに関するいくつかの調査を行い、あなたの提案を試みます。それがどのように進むのかを教えてくれます。ありがとう! – Stephanie

+1

ここでループすることは、パフォーマンスの観点からは素晴らしいアプローチではありません。あなたはトップ1を使用していますが、そのクエリには順序がありません。これは、どの行を返すかわからないことを意味します。 –

0
;with weeks as ( 
    select 
     Employee, 
     datediff(week, '20000102', WorkDate) as weekNum, 
     min(WorkDate) as workDate, 
     row_number() over (
      partition by Employee 
      order by datediff(week, '20000102', WorkDate) 
     ) as rowNum 
    from emp 
    group by Employee, datediff(week, '20000102', WorkDate) 
), islands as (
    select 
     Employee, 
     min(workDate) as workDate, 
     datediff(week, min(workDate), max(workDate)) + 1 as workWeeks 
    from weeks 
    group by Employee, weekNum - rowNum 
), gaps as (
    select *, 
     datediff(week, 
      workDate, 
      lead(workDate) over (partition by Employee order by workDate) 
     ) - workWeeks as breakWeeks 
    from islands 
) 
select * from gaps 
-- where breakWeeks > workWeeks; ?? 

私はまだこの問題の完全な本質を理解していないが、ここで私は数日前に私の携帯電話上で入力された前回の試行の作業バージョンです。これは、連続して稼働している週の週数を決定し、次にそれ自身と次の実行の開始日との間の休業日数を計算します。これは、問題に対するループのないアプローチです。うまくいけば、それはあなたを解決に近づけます。

http://rextester.com/LFAH31486

関連する問題