Oracle SQL中高效的四向连接

时间:2014-12-16 19:14:11

标签: sql oracle performance left-join

我有两个表, Table1 Table2,我想加入。每个表都有两个唯一键,我们称之为 Key1 Key2 。我想要做的是 LEFT JOIN Table2到Table1 ,其中任何一个键都以四种可能的组合中的任何一种匹配:

  • Table1.Key1 = Table2.Key1
  • Table1.Key1 = Table2.Key2
  • Table1.Key2 = Table2.Key1
  • Table1.Key2 = Table2.Key2

我的问题是:有没有有效的方法来做到这一点?现在我已经想出了类似的东西,但它需要永远运行。

CREATE TABLE NEW_TABLE AS
SELECT a.*,
       CASE WHEN a.Key1 = b.Key1 THEN 1 ELSE 0 END AS match1,
       CASE WHEN a.Key1 = c.Key2 THEN 1 ELSE 0 END AS match2,
       CASE WHEN a.Key2 = b.Key1 THEN 1 ELSE 0 END AS match3,
       CASE WHEN a.Key2 = c.Key2 THEN 1 ELSE 0 END AS match4
FROM Table1 a
LEFT JOIN (Select Key1 From Table2 Where Key1 is not null) b
    on a.Key1 = b.Key1 or a.Key2 = b.Key1
LEFT JOIN (Select Key2 From Table2 Where Key2 is not null) c
    on a.Key1 = c.Key2 or a.Key2 = c.Key2
;

绝望,我知道......

编辑:以下示例数据和所需结果:

表1:

Key1     Key2     Sales    Revenue
qwer!@   dhfgfw   455      30005
asdf#$   dfg654   221      28711
edfr2#   gg%%^f   213      31667
gthy!2   awd^&5   133      13345
rf$#22   34ffgg   655      41237
bhjk%g   w3erff   122      10066
f&*yhj   dffghj   126      11004

表2:

Key1     Key2 
qwer!@   {null}
{null}   dfg654
ffgww2   ppolkk
{null}   gthy!2
jjjj33   l00kjl
nmnmnm   34ffgg
awd^&5   {null}

期望的结果:

Key1     Key2     Sales    Revenue   match1    match2    match3    match4
qwer!@   dhfgfw   455      30005     1         0         0         0
asdf#$   dfg654   221      28711     0         0         0         1
edfr2#   gg%%^f   213      31667     0         0         0         0
gthy!2   awd^&5   133      13345     1         0         1         0
rf$#22   34ffgg   655      41237     0         0         0         1
bhjk%g   w3erff   122      10066     0         0         0         0
f&*yhj   dffghj   126      11004     0         0         0         0

2 个答案:

答案 0 :(得分:4)

加入条件中的

or可能是性能问题。我建议你改用exists

SELECT a.*,
       (case when exists (select 1 from table2 b where a.Key1 = b.Key1) then 1 else 0 end) as match1,
       (case when exists (select 1 from table2 b where a.Key1 = b.Key2) then 1 else 0 end) as match2,
       (case when exists (select 1 from table2 b where a.Key2 = b.Key1) then 1 else 0 end) as match3,
       (case when exists (select 1 from table2 b where a.Key2 = b.Key2) then 1 else 0 end) as match4
FROM Table1 a;

过滤掉NULL并不重要,因为NULL无论如何都会失败。

为获得最佳效果,您需要table2(key1)table2(key2)上的索引。

答案 1 :(得分:3)

如果您只需要行的组合而不是排列(即如果table1.keytable2.key1table2.key2具有相同的值,则只返回一行),然后这应该有效:

SELECT a.*,
       CASE WHEN a.Key1 = b.Key1 THEN 1 ELSE 0 END AS match1,
       CASE WHEN a.Key1 = b.Key2 THEN 1 ELSE 0 END AS match2,
       CASE WHEN a.Key2 = b.Key1 THEN 1 ELSE 0 END AS match3,
       CASE WHEN a.Key2 = b.Key2 THEN 1 ELSE 0 END AS match4
FROM Table1 a
LEFT JOIN Table2 b
    on a.Key1 in (b.Key1, b.key2) or a.key2 in (b.key1, b.key2);

插入提供的数据,此解决方案确实有效,但需要汇总以提供您正在寻找的结果:

SELECT   a.key1,
         a.key2,
         a.sales,
         a.revenue,
         MAX (CASE WHEN a.key1 = b.key1 THEN 1 ELSE 0 END) AS match1,
         MAX (CASE WHEN a.key1 = b.key2 THEN 1 ELSE 0 END) AS match2,
         MAX (CASE WHEN a.key2 = b.key1 THEN 1 ELSE 0 END) AS match3,
         MAX (CASE WHEN a.key2 = b.key2 THEN 1 ELSE 0 END) AS match4
FROM     table1 a
         LEFT JOIN table2 b
            ON a.key1 IN (b.key1, b.key2) OR a.key2 IN (b.key1, b.key2)
GROUP BY a.key1,
         a.key2,
         a.sales,
         a.revenue;