2013-05-22 2 views
0

계정에 대한 체납 보고서를 생성하는 작업이 주어졌습니다.SQL Server Loop 결과 집합을 거꾸로

DaysInArrears는 1 열을 제외하고는 상당히 직설적입니다.

예약 된 각 지불시 계좌 체납 상태를 해결하는 쿼리를 만들었습니다. 다음 쿼리에서 채워

AgreementID DueDate  AmountDue DueTD PaidTD FirstPaymentDue ArrearsStatus RN 
184   2013-03-11 75.00  75.00 0.00 2013-03-11  1    1 
184   2013-03-25 75.00  150.00 0.00 2013-03-11  1    2 
184   2013-04-08 75.00  225.00 300.00 2013-03-11  0    3 
184   2013-04-22 75.00  300.00 300.00 2013-03-11  0    4 
184   2013-05-03 75.00  375.00 300.00 2013-03-11  1    5 
184   2013-05-20 75.00  450.00 300.00 2013-03-11  1    6 

내가 또 다른 임시 테이블이 (#ArrearsCheck) :

INSERT INTO #ArrearsCheck 
SELECT 
    AgreementID, 
    SUM(ArrearsStatus), 
    MAX(RN) 
FROM 
    #ArrearsAnalysis 
GROUP BY 
    AgreementID 

이 쿼리는 유사한 아래에 결과를 임시 테이블 (#ArrearsAnalysis)을 채 웁니다

그 다음 내가해야 할 일은 최신 연체 기록 (체납 점수 1)에 빠졌을 때 운동 할 줄을 거꾸로 뒤지는 것입니다. (체납 점수 1)

그래서 시험 위의 3 분의 1은 2013 년 3 월 5 일의 결과를 기대합니다.

계정에 결제 한 적이 없다면 FirstPaymentDue Date를 반환합니다. 계좌가 연체되지 않은 경우 NULL을 반환합니다.

여기는 비 지불 인과 비 연체자를 처리하는 데 사용되는 쿼리입니다. 위의 코드를 해결하려면 루핑에 대한 도움이 필요합니다 (*) :

SELECT 
    DISTINCT(A.AgreementID), 
    CASE WHEN (C.ArrearsTally <= 0) 
    THEN NULL 
    ELSE (CASE WHEN (C.ArrearsTally = C.PaymentCount) 
      THEN NULL 
      *ELSE 0* 
      END) 
    END AS ArrearsDate 
FROM 
    #ArrearsAnalysis AS A 
LEFT OUTER JOIN 
    #ArrearsCheck AS C ON A.AgreementID = C.AgreementID 

이 쿼리 결과는 오늘과 결과 날짜 사이의 차이 (일)를 계산하는 다음 쿼리로 전달됩니다.

답변

1

RN (행 번호?)이 순차적으로 번호가 매겨진다면 우리는 더 최근의 레코드에 ArrearsStatus = 1이 있고 앞의 레코드에 ArrearsStatus = 0이 있거나 인접하지 않은 두 개의 인접한 레코드를 찾고 있습니다. 없는). 우리는 RN을 신뢰할 수없는 경우

SELECT MAX(aa1.DueDate) AS MaxDueDate 
FROM #ArrearsAnalysis aa1 
LEFT JOIN #ArrearsAnalysis aa2 
ON aa2.RN = aa1.RN - 1 
WHERE aa1.ArrearsStatus = 1 
AND (aa2.ArrearsStatus = 0 OR aa2.ArrearsStatus IS NULL) 

, 우리는 날짜를 기준으로 조인 상태로 시작해야합니다 (AA2 ON : 우리는 가장 최근의 이러한 이벤트와 연관된 ArrearsStatus = 1 레코드의 날짜를합니다. DueDate < aa1.DueDate) 그런 다음 인접성을 설정하는 다른 방법을 찾으십시오. 중간 날짜에 세 번째 자기 조인을하고 중간 날짜가 NULL이라고 주장하면 ...)

일반적으로 집합 기반 방식이 루핑보다 나은 접근 방법입니다. 이 상황에서는 데이터가 집합 기반 접근법을 비실용적으로 만드는 경우에만 커서 루프를 사용합니다.

aa1.AgreementID 그룹을 추가 할 수 있습니다. #ArrearsCheck가 필요하다고 생각하지 않습니다.

UPDATE

대답은 위의 원래로 표현한 질문에 적용

"그들이 최신 체납에 빠진 때 운동". "최초의 연체료"에 관한 질문은 실제로 조금 더 흥미 롭습니다. AgreementID가 처음부터 체납되어 있고 0에서 1로 전환 된 적이없는 경우에만 초기 DueDate를보고 싶기 때문에 MIN()으로 전환 할 수 없습니다.

가장 간단한 해결책 각 케이스에 대해 MIN() 날짜를 찾아 내고 그 두 값 중 MAX()를 선택하십시오. Null은 집계에서 벗어나야합니다.

SELECT b.AgreementID, 
MAX(b.MinDueDate) AS FirstArrearsDate 
FROM (
SELECT aa1.AgreementID, 
MIN(aa1.DueDate) AS MinDueDate 
FROM #ArrearsAnalysis aa1 
LEFT JOIN #ArrearsAnalysis aa2 
ON aa2.RN = aa1.RN - 1 
WHERE aa1.ArrearsStatus = 1 
AND aa2.ArrearsStatus = 0 
GROUP BY aa1.AgreementID 
UNION ALL 
SELECT aa1.AgreementID, 
MIN(aa1.DueDate) AS MinDueDate 
FROM #ArrearsAnalysis aa1 
LEFT JOIN #ArrearsAnalysis aa2 
ON aa2.RN = aa1.RN - 1 
WHERE aa1.ArrearsStatus = 1 
AND aa2.ArrearsStatus IS NULL 
GROUP BY aa1.AgreementID 
) AS b 
GROUP BY b.AgreementID 
+0

안녕 행 번호가 정확하고 신뢰할 수 있습니다. 내가 가진 문제는 계약서가 연체 된 것으로 간주되는 가장 빠른 날짜가 필요하다는 것입니다. 그렇지만, 나는 0이 지나면 가장 초기의 1을 알고 싶다. 코드를 위의 쿼리 * (*)에 붙여 넣은 다음 aa1.AgreementID = A.AgreementID에 추가했습니다. 위 결과는 1900-01-01이었습니다. –

+0

@ 리차드 업데이트를 추가했습니다. – criticalfix

관련 문제