如何使用嵌套while循环提高性能?

时间:2017-08-30 19:59:53

标签: sql-server tsql sql-server-2012

我必须根据以下链接更新标志。我的逻辑与下面提到的逻辑(在链接中)完全相同,在while循环中还有2个嵌套循环。

How To check minimum Date in each observation and update flag dynamically

但是,逻辑工作正常并且可以在几行中顺利运行。我有大约150000行(将来会更多),这种循环永远不会结束。我检查了显示计划,它说排序成本是322112%,表扫描成本是242938%。每一行都是循环的。 反正我们可以让这段代码运行得更快吗?

3 个答案:

答案 0 :(得分:2)

Here is another way to approach it using a recursive common table expression and cross apply():

test setup:

response: 
{ 
  ServiceName: { 
    ErrLog: 'Failed on each [App] instance. [App] http://..... got back error: [App] http://..... got back error: [App] http://.... got back error:',
    result: false 
  } 
}

query:

true

rextester demo: http://rextester.com/KADM27580

returns:

result

答案 1 :(得分:0)

As stated in the comments... think SET BASED when dealing with SQL.

$PCList = "C:\Scripts\Get-ADComputers\Win7.txt" 

foreach ($PC in Get-Content $PCList) {
    if (-not(Test-Connection -ComputerName $pc -BufferSize 16 -Count 2 -Quiet)) {
        Write-Host "$pc is not reachable" -ForegroundColor "yellow"
    } else {
        Invoke-Command -ComputerName $pc -ScriptBlock {
            $Session = New-Object -ComObject "Microsoft.Update.Session"
            $Searcher = $Session.CreateUpdateSearcher()
            $historyCount = $Searcher.GetTotalHistoryCount()
            $Searcher.QueryHistory(0, $historyCount) |
                Where-Object {$_.title -like "*KB4019264*"} |
                Select-Object Date,
                    @{name="Operation"; expression={switch($_.operation){1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}}}},
                    @{name="Status"; expression={switch($_.resultcode){1 {"In Progress"}; 2 {"Succeeded"}; 3 {"Succeeded With Errors"}; 4 {"Failed"}; 5 {"Aborted"}}}},
                    Title
        } | Out-GridView
    }
}

答案 2 :(得分:0)

这种逻辑很完美,但我知道这绝对可以用更好的方式编写。如果你们有任何好的替代方法,我很乐意更新我的代码: - )..

--drop table #t
    create table #t ( ID Int , StartDate Date , EndDate Date , LoopLogic nvarchar(100) ) 
    insert into #t ( ID , StartDate , EndDate ) Values 
     (1,'2017-01-01','2017-02-01')
    ,(1,'2017-01-09','2017-01-28')
    ,(1,'2017-04-01','2017-04-30')
    ,(1,'2017-04-05','2017-05-20')
    ,(1,'2017-04-20','2017-06-12')
    ,(2,'2017-06-02','2017-06-20')
    ,(2,'2017-06-14','2017-07-31')
    ,(2,'2017-06-14','2017-07-31')
    ,(2,'2017-06-19','2017-07-31')
    ,(2,'2017-06-19','2017-07-31')
    ,(3,'2017-01-01','2017-02-01')
    ,(3,'2017-02-01','2017-02-28')
    ,(3,'2017-04-01','2017-04-30')
    ,(3,'2017-06-01','2017-05-20')
    ,(3,'2017-08-01','2017-06-12')
    --drop table #auth
    select *
    into #auth 
    from #t
    order by ID,StartDate

    Declare
    @LoopLogic As nvarchar(100) = '0'
    ,@Flag As int=0
    ,@StartDate As Date
    ,@LookupDate1 As Date
    ,@LookupDate As Date
    ,@ID As nvarchar(100)
    ,@PrevID As nvarchar(100) = '0'
    ,@DaysDiff As int
    ,@ReauthFlag As int=0;

    --drop table #Temp_SO_Check
    Select
        *
    Into #Temp_SO_Check
    From #auth;

    CREATE  INDEX IDX_C_Users_UserID ON #Temp_SO_Check(ID,StartDate,LoopLogic);


    --Select * From #Temp_SO_Check As tsc  order by auth#,servicedate

    While Exists
    (
        Select Top 1
                   ID
            From    #Temp_SO_Check
            Where   LoopLogic Is Null
    )
    Begin
        Select Top 1
                    @ID = ID
                    , @StartDate = StartDate
            From    #Temp_SO_Check
            Where   LoopLogic Is Null
            Order By
                    ID
                    , StartDate;

    If @PrevID <> @ID
    Begin
            set @Flag=1;
            Set @LoopLogic ='Initial_'+Cast(@Flag as nvarchar(50)) ;
            Set @PrevID = @ID;
            set @ReauthFlag=0;
    end 
          else 
    Begin
    if((@LookupDate is not null) and (datediff(day,@LookupDate,@StartDate))<14)-- if the startdate is less than 14 days from lookdate then it is reauth
    Begin       
             Set @LoopLogic ='Re-Auth_'+Cast(@Flag as nvarchar(50)) ;
    End
    Else if ((@LookupDate is not null) and (datediff(day,@LookupDate,@StartDate))>14) -- if the startdate is greater than 14 days from lookdate then it is Initial
    Begin
             set @Flag=@Flag+1;
             set @ReauthFlag=0;
             Set @LoopLogic ='Initial_'+Cast(@Flag as nvarchar(50));
    End
    End
             Set @LookupDate = DateAdd(Day, 30, @StartDate);
    if( (@LoopLogic like '%Re-Auth_%') and (@LookupDate<>@LookupDate1))
    Begin
             Set @ReauthFlag=@ReauthFlag+1;
             Set @LoopLogic ='Re-Auth_'+Cast(@Flag as nvarchar(50))+'_'+Cast(@ReauthFlag as nvarchar(50)) ;

    End
             set @LookupDate1=@LookupDate;

    Update
            #Temp_SO_Check
            Set
            LoopLogic = @LoopLogic
            Where
            ID = @ID
            And StartDate Between @StartDate
                        And     @LookupDate;

    End;
    select * from #Temp_SO_Check