2013-01-18 1 views
1

(SQL SERVER 2008) master/base 테이블에 조인 할 레코드가 여러 테이블에 타임 스탬프가 있습니다. 시간대는 때로는 기본 표와 같지만 때로는 그렇지 않습니다.SQL 외부 조인 시간 Null 값 바꾸기

코드 테이블을 만들려면 다음

create table base (time float); 
create table table2 (time float, val2 char(1)); 
create table table3 (time float, val3 int); 
insert into base values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); 
insert into table2 values (1, 'a'),(5, 'z'),(6, 'm'),(9, 'b'); 
insert into table3 values (1.5, 1),(5.3, 10),(5.5, 0),(8.1, 4); 

결과 세트는 기본 테이블과 다른 테이블에서 "가장 최근의"값에서 레코드 당 하나 개의 행을해야합니다. 이전에는 이러한 테이블이 Vlookup을 TRUE로 설정하여 Excel에서 "조인"되었습니다.이 테이블은 정렬 된 테이블에서 가장 근접없는 일치를 나타냅니다.

time | val2 | val3 
1 | a | NULL 
2 | a | 1 
3 | a | 1 
4 | a | 1 
5 | z | 1 
6 | m | 0 
7 | m | 0 
8 | m | 0 
9 | b | 4 
10 | b | 4 

가 어떻게이 SQL 문이를 복제 할 수 있습니다 : 같은

최종 결과를보고해야합니까?

놀랍게도 ~ 100 개의 레코드 만 있기 때문에 효율성에 비해 가독성을 높일 것입니다.

+0

어떻게 base''에서 시간과 관련된 table3''에서의 시간 1.5. –

답변

3

아마도 가장 읽을 수 select 절에 상관 하위 쿼리입니다 : 나는 일반적으로 아니에요

은 팬 selectselect 내에 있지만 상관 된 하위 쿼리는 Excel vlookup의 동작을 모방합니다.

http://sqlfiddle.com/#!3/3545e/18

Select 
    b.time, 
    (Select max(t2.val2) From table2 t2 Where b.time >= t2.time) As val2, 
    (Select max(t3.val3) From table3 t3 Where b.time >= t3.time) As val3 
From 
    base b 
Order By 
    b.time;  

은 (위의 코드와 SQL 바이올린 당신에게 로렌스 감사드립니다.)

max의 사용은 값이 비 감소 있어야합니다. 다음 버전에 관계없이 작동합니다

select 
    b.time, 
    (select top 1 t2.val2 from table2 t2 where b.time >= t2.time order by t2.time Desc) as val2, 
    (select top 1 t3.val3 from table3 t3 where b.time >= t3.time order by t3.time Desc) as val3 
from 
    base b 

http://sqlfiddle.com/#!6/a5148/5

+0

@Laurence. . . 고맙습니다. 나는 지난 5 분 동안 그 코드를 해답에 넣으려고했다. –

+0

아무 걱정도없고, 훨씬 깔끔하고 내 테이블보다 더 많은 테이블로 확장됩니다. – Laurence

+0

정확한 버전은'select top 1 t2.val입니다. . . order by time desc'을 입력하십시오. –

2

두 번째 테이블에 일치하는 항목이 없더라도 외부 조인을 사용하여 결과를 얻는 것이 일반적인 원칙입니다. 그런 다음 불평등을 사용하여 넘어가는 것을 제한하고 max은 남은 것 중 가장 높은 것을 선택합니다.

본질적으로 교차 결합이 t2t3이므로 큰 테이블의 경우 비효율적 일 수 있습니다. 각에게 중첩 된 쿼리를 수행하는 더 나은, 그 후 결과에 가입 할 수 있습니다

-- Easier to read  
Select 
    b.time, 
    max(t2.val2) As val2, 
    max(t3.val3) As val3 
From 
    base b 
    left outer join 
    table2 t2 
    on b.time >= t2.time 
    left outer join 
    table3 t3 
    on b.time >= t3.time 
Group By 
    b.time 
Order By 
    b.time; 

-- Probably faster 
Select 
    n.time, 
    n.val2, 
    Max(t3.val3) 
From (
    Select 
     b.time, 
     Max(t2.val2) As val2 
    From 
     base b 
     left outer join 
     table2 t2 
     On b.time >= t2.time 
    Group By 
     b.time 
    ) n 
    Left Outer Join 
    table3 t3 
    On n.time >= t3.time 
Group By 
    n.time, 
    n.val2 
Order By 
    n.time; 

http://sqlfiddle.com/#!3/3545e/15

+0

원본 예제 테이블이 약간 오도했습니다.이 문제를 해결하기 위해 SQL 테이블 문을 편집했습니다. Val2와 Val3은 시간이 지남에 따라 항상 증가하는 것은 아니므로 MAX()는이 방식으로 사용되어 이후에 캡처하지 못합니다. 나는 모든 다음 값들의 MAX 값을 원하지 않는다. 대신, table2.time <= base.time이 최대 인 값 테이블의 값이 필요합니다. –