SQL:匹配两个具有两种可能条件的表

时间:2016-02-07 10:56:53

标签: sql oracle join

在我们加入两个表table_A和table_B时是否有一种方法在SQL中,如果我们无法匹配条件上的两个表,则说我们会尝试第二个条件criteria_Y

这样的事情:

select *
from table_A, table_B
where table_A.id = table_B.id2
and (if there is no row where table_B.criteria_X = X then try table_B.criteria_Y = Y)

以下查询不是解决方案:

..
and (table_B.criteria_X = X OR table_B.criteria_Y = Y)

由于

2 个答案:

答案 0 :(得分:0)

这是找到最佳匹配查询:

select * 
from
 (
   select *,
      row_number() -- based on priority, #1 criteria_X, #2 criteria_Y 
      over (partition by table_A.id 
            order by case when table_B.criteria_X = X then 1
                          else 2
                     end) as best_match
   from table_A, table_B
   where table_A.id = table_B.id2
   and (table_B.criteria_X = X OR table_B.criteria_Y = Y)
 ) dt
where best_match = 1

如果OR条件导致索引访问权限丢失,您可以尝试将其拆分为两个UNION ALL选项。

答案 1 :(得分:0)

典型方法使用left join两次。 。 。每个标准一次。然后在coalesce()中使用select。并且,使用连接键上的索引,这也应该具有非常好的性能:

select a.*, coalesce(b1.colx, b2.colx)
from table_A a left join
     table_B b1
     on a.id = b1.id2 and b1.criteria_X = X left join
     table_B b2
     on a.id = b1.id2 and b2.criteria_Y = Y 
where b1.id2 is not null or b2.id2 is not null;

where子句确保至少有一行匹配。

这在所有情况下都不起作用 - 特别是,每个连接只需要返回0或1个匹配的行。这通常是这种“优先”连接的情况。

替代版本使用row_number()。这类似于@dnoeth的方法,但行号计算在连接之前完成:

select a.*, coalesce(b1.colx, b2.colx)
from table_A a join
     (select b.*,
             row_number() over (partition by id2
                                order by (case when criteria_x = X then 1
                                               when criteria_y = Y then 2
                                          end)
                               ) as seqnum
      from table_B b
      where criteria_x = X or criteria_y = Y
     ) b
     on a.id = b.id2 and seqnum = 1