2011-02-18 5 views
2

간단하게 유지하려면 내 질문은 THIS QUESTION, PART 2과 비슷하지만 문제는 Oracle을 실행하지 않아서 rownumbers를 사용할 수 없다는 것입니다. 자세한 내용과 예제 필요로하는 사람들을 위해 각 계약서의 마지막 두 번째 마지막 레코드를 비교하십시오.

:

나는 테이블을

 
    contractId date   value  
    1   09/02/2011  A   
    1   13/02/2011  C   
    2   02/02/2011  D 
    2   08/02/2011  A 
    2   12/02/2011  C 
    3   22/01/2011  C 
    3   30/01/2011  B 
    3   12/02/2011  D  
    3   21/01/2011  A 

편집이 :가 ContractID의 또 다른 라인을 추가했다. 나는 몇 가지 코드를 자신했지만, 그것은 다음과 같은 표시 것 때문에 :

 
    contractId date   value value_old 
    1   09/02/2011  A     
    2   08/02/2011  A   D 
    3   30/01/2011  B   C  
    3   30/01/2011  B   A 

을하지만 그건 내가 원하는 하지입니다! 결과는 여전히 아래와 같아야합니다!

이제 특정 날짜 이전에 마지막 레코드를 선택하고 이전 값과 비교하려고합니다. 은 '주어진 날짜가'예에 2011년 11월 2일입니다 가정, 출력은 다음과 같이해야합니다 :

 
    contractId date   value value_old 
    1   09/02/2011  A     
    2   08/02/2011  A   D 
    3   30/01/2011  B   C  

내가 지정한 날짜 이전에 마지막 레코드를 선택하는 쿼리를해야합니까. 그것은 쉬운 부분입니다. 하지만 을 선택하기 전에을 잃어 버렸습니다 ...

저는 여기서 몇 가지 도움을 얻을 수 있기를 바랍니다. 며칠 동안 머리를 아프게하고 웹 및 stackoverflow에서 답변을 찾고 있습니다.

답변

3

하나의 가능성은 :

약속대로
SELECT a.contractId, a.Date, a.Value, (SELECT Top 1 b.[Value] 
     FROM tbl b 
     WHERE b.[Date] < a.[Date] And b.ContractID=a.ContractID 
     ORDER BY b.[Date] Desc) AS Old_Value 
FROM tbl AS a 
WHERE a.Date IN 
     (SELECT TOP 1 b.Date 
     FROM tbl b 
     WHERE b.ContractID=a.ContractID 
     AND b.Date < #2011/02/11# 
     ORDER BY b.date DESC) 
+0

이 방법은 작동하지 않습니다 @Remou를, 그것은 단지 하나 개의 데이터 행을 줄 것이다 '톱 1'방법. 이전에 해본 답은 조인이 많았지 만 지금은 삭제되었다고 생각합니다. 이제는 3 개의 별도의 쿼리로 덮어 씁니다. 첫 번째 행은 마지막 행, 두 번째 행은 두 번째 행, 세 번째 행은 두 개를 결합합니다. 아마도 능률적이지는 않지만, 지금 당장은 최고입니다. 나중에 상세한 답변을 게시 할 예정입니다. 실제로 사람들이 어떻게 자신의 역사 테이블에서 데이터를 비교하는지 궁금합니다 .... – Yoh

+0

@Yohsoog 나는 쿼리를 변경했습니다. 계약 ID 1에 대한 이전 값이없는 이유는 분명하지 않기 때문에 위의 쿼리에는 해당 ID에 대한 이전 값이 포함되어 있습니다. – Fionnuala

+0

@Remou 나중에 업데이트를 테스트하겠습니다.하지만 ID 1에 대한 이전 값이없는 이유는 2010 년 11 월 11 일인 'given date'에 대한 텍스트 중간에 설명 된 '필터'를 놓친 것입니다. 따라서 주어진 날짜에 ID 1의 최신 값은 A이며 그 전에 A에 대해 알려진 값이 없습니다. – Yoh

0

, 나 또한 내 대답을 게시 할 것입니다. 비록이 시점에서, 나는 여전히 Remou의 대답이 더 낫다고 생각한다. 왜냐하면 코드가 더 짧고 더 효율적인 것처럼 보이기 때문이다 (같은 테이블을 더 적게 호출한다). 그러나 여기 간다 :

에 Query1 :

SELECT c.contractID, c.firstofdates, a.value, d.value, d.date 
FROM (table1 AS A RIGHT JOIN (SELECT b.cid,max(b.date) AS FirstOfdates 
FROM table1 as B 
where b.date < #02/11/2011# 
GROUP BY b.contractID ) AS c ON (a.date = c.firstofdates) AND (a.contractID = c.contractID)) 
LEFT JOIN (select e.contractID, e.date, e.value 
from table1 as e 
) AS d ON (d.date < c.firstofdates) AND (d.contractID = c.contractID); 

이 쿼리는 실제로 3 contractID에 대한 별도의 행이 결과를 제공합니다.

QUERY2 :

SELECT b.contractID, max(a.date) AS olddate 
FROM table1 AS a RIGHT JOIN (select contractID, firstofdates 
from Query1) AS b ON (a.contractID= b.contractID) AND (a.date < b.firstofdates) 
GROUP BY b.contractID; 

그리고 모두 결합 :

QUERY3 : 당신이 사용하기 때문에

SELECT Query1.contractID, Query1.firstofdates AS [date], Query1.A.value AS [value], Query1.d.value AS [old value] 
FROM Query1 RIGHT JOIN Query2 
ON (Query1.date=Query2.olddate or Query2.olddate is null) AND (Query1.cid = Query2.cid); 
관련 문제