2016-10-05 2 views
0

SQLServer2008을 사용하고 있으며 전에 본 적이없는 문제가 발생했습니다. 몇 가지 값이 각 분기마다 여러 번 복제되는 데이터 집합이 있습니다. 각 분기에 가장 최근 값을 선택하려고합니다.조인 된 테이블의 다른 필드를 기준으로 가장 최근 값을 선택하십시오.

SELECT PPAV.BusinessID 
         , (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) AS Quarter 
         , PAV.PartnerAttributeValue 
        FROM Partner_PartnerAttributeValue PPAV 
        JOIN PartnerAttributeValue PAV 
         ON PAV.PartnerAttributeValueID = PPAV.PartnerAttributeValueID 
        WHERE PAV.PartnerAttributeID = 7 
         AND (PPAV.PartnerAttributeValueID = 22 OR PPAV.PartnerAttributeValueID = 795 OR PPAV.PartnerAttributeValueID = 796) 

        GROUP BY PPAV.BusinessID 
          , (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) 
          , PAV.PartnerAttributeValue 

이것은 문제가 발생한 코드입니다. 나는 분기당 하나의 가치만을 원합니다. 때로는 분기 중반에 변경 사항이 있으며 정보가 복제됩니다. 이 문제를 해결하려고 시도했을 때이 코드를 사용하고 있었고 문제점 쿼터가 4 개의 값을 갖도록함으로써 실제로 문제를 악화 시켰습니다.

SELECT PPAV.BusinessID 
         , (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) AS Quarter 
         , CASE WHEN (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) = (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) 
          THEN SubHist.PartnerAttributeValue 
          ELSE PAV.PartnerAttributeValue 
          END AS PartnerAttributeValue 
       FROM Partner_PartnerAttributeValue PPAV 
       JOIN PartnerAttributeValue PAV 
        ON PAV.PartnerAttributeValueID = PPAV.PartnerAttributeValueID 
       JOIN (SELECT PPAV.BusinessID 
            , MAX(PPAV.PartnerAttributeValueStartDate) AS MAX 
            , PAV.PartnerAttributeValue 
           FROM Partner_PartnerAttributeValue PPAV 
           JOIN PartnerAttributeValue PAV 
            ON PAV.PartnerAttributeValueID = PPAV.PartnerAttributeValueID 
           WHERE PAV.PartnerAttributeID = 7 
           AND (PPAV.PartnerAttributeValueID = 22 OR PPAV.PartnerAttributeValueID = 795 OR PPAV.PartnerAttributeValueID = 796) 
           GROUP BY PAV.PartnerAttributeValue 
             ,PPAV.BusinessID 
         )SubHist 
        ON SubHist.BusinessID = PPAV.BusinessID 
       WHERE PAV.PartnerAttributeID = 7 
        AND (PPAV.PartnerAttributeValueID = 22 OR PPAV.PartnerAttributeValueID = 795 OR PPAV.PartnerAttributeValueID = 796) 
       GROUP BY PPAV.BusinessID 
         , (cast(year(PPAV.PartnerAttributeValueStartDate) as char(4)) + '0' + cast(datepart(qq, PPAV.PartnerAttributeValueStartDate) as char(1))) 
         , PAV.PartnerAttributeValue 
         , SubHist.PartnerAttributeValue 

나는 문제를 악화시키기 위해 무엇을했는지 매우 확신하지 못한다. 추가 된 조인 된 테이블에서 오는 CASE WHEN 문이 문제를 해결할 것이라고 생각했습니다.

도움을 주시면 대단히 감사하겠습니다. 다음은

내가

4356 201501 REGISTERED 
4356 201502 REGISTERED 
4356 201503 REGISTERED 
4356 201504 REGISTERED 
4356 201601 GOLD 
4356 201601 REGISTERED 
4356 201602 REGISTERED 
4356 201603 REGISTERED 
4356 201604 REGISTERED 

2016 년 1 분기 데이터가로 인해 왜곡됩니다, 여러 값을 가지고 어디에 문제를 제거하기 위해 노력하고 일부 샘플 데이터입니다. 골드 값과 GOLD 값만 있어야합니다.

고마워요!

+0

분기당 하나의 값을 원하지만 분기의 값이 둘 이상일 수 있습니다. 예를 들어 SUM과 같은 집계 함수를 사용해야한다고 생각합니다. –

+0

당신이'row_number()와 같은 윈도우 함수를 사용할 수있는 것처럼 보입니다. (PartnerID에 의한 파티션, 분기, Order by PartnerAttributeValueStartDate desc) RN' 서브 클래스 나 cte 안에 랩핑 한 다음'RN = 1 '을 추가하십시오. – xQbert

+0

확실하지 않습니다. 합계가 작동합니다. 이것은 더 큰 쿼리의 작은 하위 집합입니다. 값은 문자 값이므로 분기가 같은 최대 날짜의 문자 값이 필요합니다. 이 쿼리는 ROW_number 트릭을 사용하는 더 큰 CTE의 일부일뿐입니다. 더 큰 함수의 성능은 이미 매우 좋지 않습니다. ( – Gollathor

답변

2

창 기능을 사용하여 각 분기 및 비즈니스 ID에 대한 행 번호를 생성하십시오. 그런 다음 각 그룹의 첫 번째 행 번호 (RN)로 제한하십시오 ...

RN은 우리가 제한 할 수 있기 전에 생성되어야하므로 CTE 또는 하위 쿼리로 래핑 한 다음 RN = 1을 적용합니다. .

  1. 가 가독성과 가능성 성능에 대한에있을 당신의 OR 문을 전환 : 또한 내가

    .

  2. + 문자열 집계 대신에 concat을 사용하도록 분기 계산을 수정했습니다. (유효한 날짜를 처리하는 경우에는 암시 적 변환에 의존해야합니다.)

이러한 추가 변경으로 인해 구문 오류가 발생할 수도 있습니다.

UNTESTED 아래의 표 구조와 예제 데이터가 SQL Fiddle에 제공된 경우이를 테스트 할 것입니다.

Select * from (

    SELECT PPAV.BusinessID 
     , concat(year(PPAV.PartnerAttributeValueStartDate) 
        , '0' 
        ,datepart(qq, PPAV.PartnerAttributeValueStartDate) 
       ) 
      AS Quarter 
     , PAV.PartnerAttributeValue 
     , row_number() 
      Over (PARTITION BY PPAV.BusinessID 
       , year(PPAV.PartnerAttributeValueStartDate) 
       , datepart(qq, PPAV.PartnerAttributeValueStartDate)) 
       ORDER BY PartnerAttributeValueStartDate DESC) RN 
    FROM Partner_PartnerAttributeValue PPAV 
    JOIN PartnerAttributeValue PAV 
     ON PAV.PartnerAttributeValueID = PPAV.PartnerAttributeValueID 
    WHERE PAV.PartnerAttributeID = 7 
     AND PPAV.PartnerAttributeValueID IN (22, 795,796) 
    GROUP BY PPAV.BusinessID 
      , concat(year(PPAV.PartnerAttributeValueStartDate) 
        , '0' 
        ,datepart(qq, PPAV.PartnerAttributeValueStartDate) 
       ) 
      , PAV.PartnerAttributeValue) cte 

from cte where RN = 1 
+0

나는 다시 함께 모으지 않고 연도와 분기 부분에 파티션을 지정하는 것이 좋습니다. 그렇게하는 것이 이점이 있습니까? '그룹 바이 '와 같은 이야기 맞지? – shawnt00

+0

좋지 않은 점은 ... 그리고 아마도 시작 날짜를 기준으로 정렬해야합니다 대신 기본 오름차순을 허용합니다 ... – xQbert

+0

나는 하위 쿼리 내에서 CTE를 실행할 수 있다고 생각하지 않습니다. 나는이 쿼리가 훨씬 더 큰 쿼리의 조인이라는 사실에 좀 더 구체적 이어야만했다. – Gollathor

관련 문제