SQL外部联接时间替换空值

时间:2013-01-18 19:27:02

标签: sql sql-server sql-server-2008 timestamp outer-join

(SQL SERVER 2008) 我在多个表中加上时间戳记以加入主/基表。时间点有时等于基表,但有时不等。

创建表格的代码:

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条记录,我会在这里考虑效率。

2 个答案:

答案 0 :(得分:3)

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

我通常不是selectselect的粉丝,但相关子查询确实模仿了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

(感谢Laurence上面的代码和SQL Fiddle。)

使用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

答案 1 :(得分: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