2017-12-15 13 views
0

커서가 현재 형식에서 다음과 같은 원하는 출력을 얻지 못하게하려고합니다. 현재 커서를 사용해야하고 데이터 세트가 매우 커서 실행하기 위해 약 2 시간이 걸립니다. 커서를 여기SQL 서버에서 커서 피하기

Here is the current date format and desired output 을 피할 수있는 방법이

Declare @CustomerId CHAR(8) 
Declare @StartDate DateTime 
Declare @PlStartDate DateTime 
Declare @ProviderNo CHAR(8) 
Declare @Code CHAR(3)  

Declare @PreviousCustomerId CHAR(8) 
Declare @PreviousStartDate DateTime 
Declare @PreviousRealStartDate DateTime 
Declare @PreviousProviderNo CHAR(8) 
Declare @PreviousCode CHAR(3)   
Declare @RowNumber smallint 
Declare @providers CURSOR 

SET @providers = CURSOR FAST_FORWARD FOR 
Select CustomerId, StartDate, PlStartDate, ProviderNo, Code, ProviderSSN, RowNumber 
From dbo.[provider] ORDER by CustomerId, StartDate 

OPEN @providers 
FETCH NEXT From @providers INTO @CustomerId, @StartDate, @PlStartDate,@ProviderNo, @Code, @ProviderSSN, @RowNumber 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    If @RowNumber <>1 AND @CustomerId = @PreviousCustomerId AND @Code = @PreviousCode AND (@ProviderNo = @PreviousProviderNo)  
    BEGIN 
     Update dbo.provider 
     SET StartDate = @PreviousRealStartDate 
     Where CustomerId = @CustomerId AND StartDate = @StartDate;  
    END 
    ELSE 
    BEGIN 
     Set @StartDate = @StartDate; 

     Update dbo.provider 
     Set StartDate = @StartDate 
     Where CustomerId = @CustomerId AND StartDate = @StartDate 
    END 

    Set @PreviousCustomerId = @CustomerId 
    Set @PreviousCode = @Code  
    Set @PreviousProviderNo = @ProviderNo 
    if @StartDate IS NOT NULL 
     Set @PreviousRealStartDate = @StartDate 
    Set @PreviousStartDate = @StartDate 

    FETCH NEXT From @providers INTO @CustomerId, @StartDate, @PlStartDate,@ProviderNo, @Code, @RowNumber   
END 

CLOSE @providers 
DEALLOCATE @providers 

현재 형식 내 현재 코드

    
Cust ID Start Date  End Date Code Provider 
7063903 2/11/2009 2/17/2009 DEF 485960 
7063903 2/17/2009 2/24/2009 DEF 485960 
7063903 2/24/2009 4/6/2009 LHF 479407 
7063903 4/6/2009 9/11/2009 DEF 487398 
7063903 8/31/2010 9/1/2010 DEF 487398 
7063903 8/28/2011 11/25/2011 ABC 531428 
7063903 3/1/2012 6/25/2012 DEF 487398 
7063903 6/25/2012 3/22/2013 DEF 487398 
7063903 3/22/2013 4/23/2014 DEF 487398 
7063903 4/23/2014 5/1/2014 DEF 487398 
7063903 5/1/2014 7/1/2015 DEF 487398 
7063903 7/1/2015 8/28/2015 DEF 531428 
7063903 8/28/2015 11/25/2015 ABC 531428 
7063903 11/25/2015 9/21/2016 ABC 531428 

Desired Output    

CustID Start Date End Date Code Provider 
7063903 2/11/2009 2/24/2009 DEF 485960 
7063903 2/24/2009 4/6/2009 LHF 479407 
7063903 4/6/2009 9/1/2010 DEF 487398 
7063903 8/28/2011 11/25/2011 ABC 531428 
7063903 4/6/2009 7/1/2015 DEF 487398 
7063903 7/1/2015 8/28/2015 DEF 531428 
7063903 8/28/2015 9/21/2016 ABC 531428 
+0

브라이언

감사합니다, 당신은 우리의 데이터는 제안 된 솔루션을 테스트하는 것을 사용할 수있을 것입니다, 텍스트로 데이터의 그 샘플을 제공합니다. 미래의 텍스트 테이블 사용. –

+0

@Used_By_ 이미 텍스트 테이블에 데이터를 추가했습니다. – CoolArsh

답변

0

예, 대신 윈도우 함수를 사용하여 LAG의 사용을 고려()

이 있습니다
Select 
     CustomerId 
     , StartDate 
     , PlStartDate 
     , ProviderNo 
     , Code 
     , ProviderSSN 
     , RowNumber 
     , LAG(StartDate) OVER(PARTITION BY CustomerId, Code, ProviderNo 
          ORDER by StartDate) as lag_date 
From dbo.[provider] 
WHERE StartDate IS NULL 
ORDER by CustomerId, StartDate 

올바른 경우이 작업을 수행 할 수 있습니다. 공통 표 표현식을 작성한 다음이를 사용하여 갱신하십시오. 뭔가 작은 것을 먼저 테스트하십시오. 예 : 공급자는 다음과 같이 반복되면

with cte as (query shown above) 
update cte 
set StartDate = lag_date 
1
SELECT customer 
     , code 
     , provider 
     , MIN (start_date) start_date 
     , MAX (end_date) end_date 
    FROM dbo.provider 
GROUP BY customer, code, provider; 

이 솔루션은 실패한다. 빨간색 화살표 봐 :

updatred

톰,

내가 사과해야합니다, 나는 원래의 문제를 오해. 고객/코드/공급자가 동일하고 시작 날짜 = 이전 종료 날짜 인 응답을 그룹화합니다.

아래의 SQL은 고객/코드/공급자가 일치하지 않거나 시작 날짜가 이전 종료 날짜와 같지 않을 때마다 값 1을 설정하여이 작업을 수행합니다. 그런 다음 이전 레코드의 1을 모두 합하여 그룹화 할 수있는 값을 만듭니다. 그런 다음 그룹을 포함하여 이번에는 원래 응답과 마찬가지로 최대/최소값을 수행합니다.

한 가지 예외를 제외하고 요청한 답변과 동일한 답변을 제공합니다. 첫 번째 화살표는 한 행이 아니라 두 행으로 이루어져야합니다. 시도해주세요.

WITH 
    aset 
    AS 
     (SELECT customer 
       , code 
       , provider 
       , start_date 
       , end_date 
       , CASE 
        WHEN LAG (customer) 
          OVER (
           PARTITION BY customer, code, provider ORDER BY end_date 
          ) = customer 
        AND LAG (provider) 
          OVER (
           PARTITION BY customer, code, provider ORDER BY end_date 
          ) = provider 
        AND LAG (code) 
          OVER (
           PARTITION BY customer, code, provider ORDER BY end_date 
          ) = code 
        AND LAG (end_date) 
          OVER (
           PARTITION BY customer, code, provider ORDER BY end_date 
          ) = start_date 
        THEN 
         0 
        ELSE 
         1 
       END 
        flag 
      FROM deleteme_tbl), 
    bset 
    AS 
     (SELECT customer 
       , code 
       , provider 
       , flag 
       , start_date 
       , end_date 
       , SUM (flag) 
        OVER (
         ORDER BY 
          customer 
          , code 
          , provider 
          , start_date 
         RANGE UNBOUNDED PRECEDING 
        ) 
        grp 
      FROM aset) 
    SELECT customer 
     , code 
     , provider 
     , MIN (start_date) start_date 
     , MAX (end_date) end_date 
    FROM bset 
GROUP BY customer 
     , code 
     , provider 
     , grp 
ORDER BY customer 
     , code 
     , provider 
     , start_date;