2013-01-08 59 views
0

如果我写这样的查询:Postgres的全外连接headscratcher

with foo as (
    select 
     'foo' as name, 
     1 as value 
    union all select 
     'foo', 2 
    union all select 
     'foo', 3 
    union all select 
     'foo', 4 
), bar as (
    select 
     'bar' as name, 
     3 as value 
    union all select 
     'bar', 4 
    union all select 
     'bar', 5 
    union all select 
     'bar', 6 
) 
select 
    f.name, 
    b.value, 
    b.name 
from 
    foo as f 
full outer join 
    bar as b 
    on b.value = f.value; 

我得到这个:

name  value name 
foo   (null) (null) 
foo   (null) (null) 
foo   3  bar 
foo   4  bar 
(null)  5  bar 
(null)  6  bar 

这是我所期望的。但是,如果我尝试做一个表值函数类似的东西,像这样:

with allSizes as (
     select cast('120X60' as character varying) as size 
     union all select '160X600' 
     union all select '1X1' 
     union all select '300X250' 
     union all select '728X90' 
     union all select '88X32' 
     union all select 'PEEL' 
) 
select 
     msd.region, 
     msd.market, 
     s.size, 
     msd.target, 
     msd.actual 
from 
     marketdata('2013-01-05') as msd 
full outer join 
     allSizes as s 
     on s.size = msd.size 
where 
     msd.market = 'Foo, USA'; 

其中marketdata()是表值函数,我不明白这是不存在的对应size列空行marketdata()功能。为什么不?

回答

3

正是因为:

where 
     msd.market = 'Foo, USA'; 

它产生的full outer join,然后过滤出不存在于所述marketdata()的行(因为它们具有msd.market = NULL

可以更改该查询于:

with allSizes as (
     select cast('120X60' as character varying) as size 
     union all select '160X600' 
     union all select '1X1' 
     union all select '300X250' 
     union all select '728X90' 
     union all select '88X32' 
     union all select 'PEEL' 
) 
select 
     msd.region, 
     msd.market, 
     s.size, 
     msd.target, 
     msd.actual 
from 
     (select marketdata('2013-01-05') 
     where market = 'Foo, USA') as msd 
full outer join 
     allSizes as s 
     on s.size = msd.size; 

或者干脆重写

where 
     msd.market = 'Foo, USA' OR msd.market IS NULL; 

如果marketdata()不返回msd.market IS NULL的行。

+0

哈!现在很明显。我很少需要使用完整的联接,所以我正在推翻它。 –

+0

@JeremyHolovacs:这对于“正常”左或右外连接也是如此(如果“外”表的列是where子句的一部分)。 –

+0

@a_horse_with_no_name,是的,这就是为什么我说现在很明显。让一个人偶尔会有脑部衰竭。 :) –