根据先前值(循环)计算值

时间:2017-01-11 18:16:22

标签: sql sql-server loops date sql-server-2012

有人可以帮我理解使用哪种功能或方向去解决下面的问题?我已经完成了脚本的大部分工作,但我仍然试图弄清楚如何从上到下一次定义一个日期。例如,计算第一行的第一个日期,然后根据第一行的第一个日期计算第二行的第二个日期。

我创建的示例表:

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周,那么我需要根据工作量为员工分配结束日期。

  1. 我定义了第一个开始日期,即所有工作日期的MIN "1/4/2016"
  2. 我寻找第一次超过3的休息时间。我看到有5周的休息时间。我必须检查一下我的工作是否超过起飞。 WorkDate减去StartDate1/28/2016 - 3/10/2016)。如果大于5周,则指定结束日期为WorkDate
  3. 然后我去找下一个。我看到4周(4/15/2016 - *05/15/2016),所以我会计算一下员工是否工作超过4周。在这种情况下,员工已经工作了5周。按之前的StartDate 3/10/2016减去4/15/2016WorkDate)计算。
  4. 我知道如何计算开始日期和结束日期,但我不确定如何一次完成这个日期,因为每个下一行都取决于之前的值。请帮忙!

2 个答案:

答案 0 :(得分: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 :(得分: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