2009-08-14 1 views
0

나는 테이블에 다음과 같은 열 (SQL 서버 2005)이이 테이블에 여러 행이 될 수있는 각 VehicleId를 들어최대 하나의 유효한 행을 날짜별로 선택하는 SQL 쿼리 w.r.t. 외래 키

State: 
- StateId INT PRIMARY KEY 
- VehicleId INT 
- ValidFromDate DATETIME 

합니다. 현재 유효한 상태 (날짜 매개 변수 포함)를 선택하고 싶습니다. 각 차량에 대해 최대 하나의 유효한 상태가있을 수 있습니다 (ValidFromDate이 날짜 매개 변수보다 작음).

테이블은 다음과 같다 경우

StateId VehicleId ValidFromDate 
---  ---  --- 
2  1   2009-06-02 
4  2   2009-06-04 

나는 다음과 같은 쿼리가 올바른 결과를 생성 생각 :

StateId VehicleId ValidFromDate 
---  ---  --- 
1  1   2009-01-01 
2  1   2009-06-02 
3  1   2009-11-03 
4  2   2009-06-04 
5  3   2009-10-05 

그리고 @Date = '2009-08-14' 나는 쿼리는 다음과 같은 결과를 생성 할

SELECT * FROM State s1 
WHERE s1.StateId IN (SELECT TOP 1 StateId 
        FROM State s2 
        WHERE s2.ValidFromDate <= @Date AND s1.VehicleId = s2.VehicleId 
        ORDER BY s2.ValidFromDate DESC, s2.StateId DESC) 

하지만 grou를 사용하여 더 좋은 방법이 있어야합니다. 핑 조항 맞지? 같은 테이블의 하위 쿼리를 사용하는 것이 옳다고 생각하지 않습니다.

답변

1

SQL 2005 RANK 절을 사용하면 "Top X by Group"문제를 해결할 수 있습니다.

이렇게 쿼리하면 문제가 해결됩니다. 참고 사항 : 귀하의 데이터가 주어지면 위의 예상 결과에서 VehicleId가 2 여야한다고 생각합니다.

SELECT dateranks.* 
FROM 
(
    select 
    s1.StateId, 
    s1.VehicleId, 
    s1.ValidFromDate, 
    RANK() OVER (PARTITION BY s1.VehicleId ORDER BY s1.ValidFromDate desc) AS 'DateRank' 
    FROM [state] s1 
    WHERE 
    ValidFromDate <= '8/14/2009' 
) 
dateranks 
where 
    dateranks.ValidFromDate <= '8/14/2009' 
    AND DateRank = 1 

유용한 링크 :

+0

이것이 작동하는 것 같습니다. 감사합니다. 전에 RANK 키워드에 대해 들어 보지 못했습니다. 이것은 내 생각에 여전히 일종의 하위 쿼리 솔루션이지만 적어도이 작업을 수행하는 올바른 방법이라고 느낍니다. 하나의 질문이지만, 두 쿼리 모두에서 'ValidFromDate <='8/14/2009''가 된 이유는 무엇입니까? – Oskar

0

TOP 1을 사용하면 길 찾기가 가능한 행이 하나만 반환됩니다. 당신이 찾고있는 결과가 이런 것 같아요.

그러나 여전히 MAX 날짜를 얻기 위해 서브 쿼리를 사용합니다. 나는 이제 다른 길을 알고있다. 그러나, 나는 이것을 많이 사용하고 빠르지는 않지만 너무 느리다는 것을 발견하지 못했습니다.

SELECT 
    * 
FROM 
    State 
WHERE 
    State.ValidFromDate = 
(
    SELECT 
     MAX(ValidDromDate) 
    FROM 
     State2 
    WHERE 
     State2.VehicleId = State.VehicleId 
    AND 
     State2.ValidFromDate <= @Date 
)