2014-11-12 3 views
1

날짜와 이름, 가격 열이있는 테이블이 있습니다. 내가하고 싶은 일은 같은 이름의 연속 날짜의 최소 날짜와 최대 날짜가있는 2 개의 열을 하나 추가하는 것입니다.DB2의 계산 된 열 참조

내가 규칙을 설명하고 다음 쿼리를 작성했습니다 :

select date1,name,price 
    case 
    when lag(name,1) over(order by date1 ASC,name ASC)=name then lag(minDate,1) over(order by date1 ASC,name ASC) 
    else date1 
    end as minDate, 
    case 
    when lag(name,1) over(order by date1 DESC,name DESC)=name then lag(maxDate,1) over(order by date1 DESC,name DESC) 
    else date1 
    end as maxDate 
    from MyTable order by date1 ASC,name ASC 

내 문제는 내가 "minDate/maxDate에 대한 잘못된 상황을"얻을 것입니다 (SQLCODE = -206, SQLSTATE = 42703) 왜 수 계산 된 열을 참조하지 않습니까? 다른 방법이 있습니까?

답변

1

maxDate이 해당 범위에 정의되어 있지 않으므로 lag(maxDate,1)에 대해 불평하고 있습니다. MyTable의 열이 아니며 이후에SELECT 목록이 DB2에서 완료 될 때까지 별칭을 사용할 수 없습니다 (서브 쿼리 또는 HAVING과 같은 절에서이 목록을 사용할 수있게됩니다).

  • LEAD(...) 반대 기능입니다

    SELECT date1, name, price, 
         LAG(date1, 1, date1) OVER(PARTITION BY name ORDER BY date1) AS minDate, 
         LEAD(date1, 1, date1) OVER(PARTITION BY name ORDER BY date1) AS maxDate 
    FROM MyTable 
    ORDER BY date1, name 
    

    (이 모든 주문에 대한 기본이야 나는이 ASC을 떠 났어요) :

    덧붙여, 쿼리 더 나은 다음과 같이 쓸 수있다 LAG(...)으로 이동하고 한 행을 앞으로으로 보입니다. 이 방법을 사용하면 옵티마이 저가 하나의 윈도우 (OVER(...)에 지정된 것) 만 계산할 수 있습니다.

  • 여기에서 윈도우 함수의 세 번째 매개 변수는 기본값입니다. 다음/이전 행이없는 경우 현재 행에서 date1을 반환합니다.
  • PARTITION BY은 본질적으로 윈도우 기능의 그룹이며 원래 쿼리에서 CASE ... WHEN ... 대신 사용됩니다. (일반적으로, 그러한 구조는 명령형 프로그래밍과 공통된 사고 방식을 반영하며, SQL의 집합 기반 특성에 반하는 경향이 있음을 알 수 있습니다. 일반적으로 더 나은 방법이 있습니다.)