2013-01-18 26 views
1

(SQL SERVER 2008) 我在多个表中加入了时间戳记录以加入主/基表。时间点有时等于基本表,但有时不。SQL外部加入时间替换空值

代码来创建表:

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); 

结果集应为每记录一列从基表和其它表中的“最近”的价值。以前,这些表在Excel中使用Vlookup设置为TRUE“加入”,这会从排序后的表中进行最接近的不进行重复匹配。

最终的结果应该是这样的:

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

如何时间从1.5'table3'从'base'与时间有关。 –

回答

3

也许最可读是select子句中的相关子查询:

我不是一般的select的粉丝在select之内,但相关的子查询确实模仿Excel vlookup的行为。

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;  

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

(谢谢劳伦斯上面的代码和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。 。 。按时间顺序排列。 –

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的值表中的值。 –