2016-03-30 32 views
1

我在三個字段中加入兩個表。我遇到的問題是如果a.baz不在b.baz中,我需要使用表b中的默認行。問題是有些會在b中有一個匹配,但也有一個默認值,並導致我不想要的交叉產品。加入默認值但不想交叉產品

select a.foo, a.bar, a.baz, b.fee, b.fie 
from a 
join b 
on a.foo = b.foo 
and a.bar = b.bar 
and ((a.baz = b.baz) or b.baz = 'DEFAULT') 

電流輸出:

foo bar baz fee fie 
bob doe NYC 500 200 
bob doe DEFUALT 100 100 
john doe DEFAULT 100 100 
jane doe NYC 500 500 

期望的輸出:

foo bar baz fee fie 
bob doe NYC 500 200 
john doe DEFAULT 100 100 
jane doe NYC 500 500 

樣本數據:

a: foo bar baz bob doe NYC john doe NYC jane doe NYC

b: foo bar baz fee fie bob doe NYC 500 200 bob doe DEFAULT 100 100 john doe CHI 300 200 john doe DEFAULT 100 100 jane doe NYC 500 100

+2

你能顯示錶中的一些示例數據嗎? –

+0

添加了一些示例數據。 – SparkeyG

+1

你得到的結果不是交叉產品。我想你的當前輸出是正確的,有問題的條件。 –

回答

2

您必須添加一個NOT EXISTS,以排除具有baz = 'DEFAULT'b記錄時匹配a.baz = b.baz也存在:

select a.foo, a.bar, a.baz, b.baz, b.fee, b.fie 
from a 
join b 
on a.foo = b.foo and a.bar = b.bar and ((a.baz = b.baz) OR b.baz = 'DEFAULT') 
where not exists (select 1 
        from b as b1 
        where a.foo = b1.foo and 
         a.bar = b1.bar and 
         b.baz = 'DEFAULT' and 
         b1.baz = a.baz) 

Demo here

+0

謝謝你,這個伎倆。 – SparkeyG

0

您的查詢是相當精細的,因爲它已經包含了行你要。現在您必須刪除不需要的行。你通過排名你的比賽來做到這一點,只保持更好的比賽。這可以用ROW_NUMBER完成,給予更好的戰績排1號。

select foo, bar, abaz, bbaz, fee, fie 
from 
(
    select 
    a.foo, a.bar, a.baz as abaz, b.baz as bbaz, b.fee, b.fie, 
    row_number() over (partition by a.foo, a.bar 
         order by case when b.baz = 'DEFAULT' then 2 else 1 end) as rn 
    from a 
    join b on b.foo = a.foo 
     and b.bar = a.bar 
     and b.baz in (a.baz, 'DEFAULT') 
) ranked 
where rn = 1; 
0

這裏就是爲了解決這個使用外另一種簡單的方法加入:

select 
    a.foo, 
    a.bar, 
    case when b.baz is null then d.baz else b.baz end as baz, 
    case when b.baz is null then d.fee else b.fee end as fee, 
    case when b.baz is null then d.fie else b.fie end as fie 
from a 
left join b on b.foo = a.foo and b.bar = a.bar and b.baz = a.baz 
left join b d on d.foo = a.foo and d.bar = a.bar and d.baz = 'DEFAULT'; 

如果費和外商投資企業不可爲空,你可以簡化爲:

select 
    a.foo, 
    a.bar, 
    coalesce(b.baz, d.baz) as baz, 
    coalesce(b.fee, d.fee) as fee, 
    coalesce(b.fie, d.fie) as fie 
from a 
left join b on b.foo = a.foo and b.bar = a.bar and b.baz = a.baz 
left join b d on d.foo = a.foo and d.bar = a.bar and d.baz = 'DEFAULT';