我在三个领域加入了两张桌子。我遇到的问题是,如果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
答案 0 :(得分:2)
您必须添加NOT EXISTS
,以便在匹配b
也存在时排除baz = 'DEFAULT'
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)
答案 1 :(得分:0)
您的查询非常好,因为它已包含您想要的行。现在,您必须删除不需要的行。您可以通过对匹配进行排名并保持更好的匹配来实现此目的。这可以使用ROW_NUMBER
来完成,从而提供更好的记录行号。
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;
答案 2 :(得分: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';
如果费用和fie不可为空,您可以将其简化为:
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';