SQL查询 - 间接连接两个表

时间:2016-06-14 09:50:45

标签: sql oracle join

我有两个表,如下所示

表1

COL1    COL2    COL3
 A       10     ABC
 A       11     ABC
 A       1      DEF
 A       2      DEF
 B       10     ABC
 B       11     ABC
 B       1      DEF
 C       3      DEF
 C       12     ABC
 C       21     GHI

表2

COL1   GHI  ABC DEF
 A1    21   10  1
 A2    21   12  1
 A3    21   10  1
 A4    23   10  1
 A5    25   11  3
 A6    21   14  3
 A7    25   11  1
 A8    23   10  1
 A9    29   10  2
 A10   21   12  3

我创建了另一个临时表,它返回tbl1.col1

中的所有不同值

tbl1中col3的值是tbl2中的列,由一些值填充。

我需要的是table1.column1,(A, B, C)的每个不同值,在这种情况下,返回 table2.column1 table1.column1 这样

  • table2.column1的ABC值匹配" group"的任何ABC值。来自table1,
  • 并且table2.column1的DEF值匹配" group"的任何DEF值。来自table1,
  • AND 如果该组包含GHI值,则table2.column1的GHI值匹配"组"的任何GHI值。来自table1

所以,我需要类似下面的内容

输出表

Table2.COL1   Table1.Col1
     A1            A
     A3            A
     A4            A
     A7            A
     A8            A
     A9            A
     A1            B
     A3            B
     A4            B
     A7            B
     A8            B          
     A10           C

我试过这样的事情,但我不确定这是否是正确的接近方式

select table2.col1, temp_distinct_table.column1 
      from table2, temp_distinct_table
      where table2.def IN (SELECT col2 
                           FROM table1 
                           WHERE table1.col1 = temp_distinct_table.col1 
                                 AND table1.col3 = 'DEF')
      AND table2.abc IN (SELECT col2 
                         FROM table1 
                         WHERE table1.col1 = temp_distinct_table.col1 
                                 AND table1.col3 = 'ABC')
      AND (
          table2.ghi IN (SELECT col2 
                          FROM table1 
                          WHERE table1.col1 = temp_distinct_table.col1  
                                 AND table1.col3 = 'GHI') 
         OR NOT EXISTS (SELECT col2 
                     FROM table1 
                     WHERE table1.col1 = temp_distinct_table.col1 
                       AND table1.col3 = 'GHI')
          )

其中temp_distinct_table包含table1.col1

中的所有不同值

有人可以就此事指导我吗?

2 个答案:

答案 0 :(得分:3)

当您使用集合时,这变得非常简单(您只需要为每个表执行一次表扫描):

Oracle安装程序

CREATE TYPE intlist AS TABLE OF INT;
/

<强>查询

SELECT t2.col1 AS t2_col1,
       t1.col1 AS t1_col1
FROM   (
  SELECT col1,
         CAST( COLLECT( CASE col3 WHEN 'ABC' THEN col2 END ) AS INTLIST ) AS abc,
         CAST( COLLECT( CASE col3 WHEN 'DEF' THEN col2 END ) AS INTLIST ) AS def,
         CAST( COLLECT( CASE col3 WHEN 'GHI' THEN col2 END ) AS INTLIST ) AS ghi
  FROM   table1
  GROUP BY col1
) t1
INNER JOIN table2 t2
ON (    t2.abc MEMBER OF t1.abc
    AND t2.def MEMBER OF t1.def
    AND ( t2.ghi MEMBER OF t1.ghi OR t1.ghi IS EMPTY ) );

<强>输出

t2_col1 t1_col1
------- -------
A1      A
A3      A
A4      A
A7      A
A8      A
A9      A
A1      B
A3      B
A4      B
A7      B
A8      B
A10     C

<强>更新

不使用集合的替代查询(它比查询更有效,但可能比集合更低效):

SELECT t2.col1,
       t1.col1
FROM   table1 t1
       CROSS JOIN
       table2 t2
GROUP BY t1.col1, t2.col1
HAVING COUNT( CASE WHEN t1.col2 = t2.abc AND t1.col3 = 'ABC' THEN 1 END ) > 0
AND    COUNT( CASE WHEN t1.col2 = t2.def AND t1.col3 = 'DEF' THEN 1 END ) > 0
AND    (  COUNT( CASE WHEN t1.col2 = t2.ghi AND t1.col3 = 'GHI' THEN 1 END ) > 0
       OR COUNT( CASE t1.col3 WHEN 'GHI' THEN 1 END ) = 0 )
ORDER BY t1.col1, t2.col1;

更新2

CROSS JOIN更改为INNER JOIN

SELECT t2.col1 AS t2_col1,
       t1.col1 AS t1_col1
FROM   (
         SELECT t1.*,
                COUNT( CASE col3 WHEN 'GHI' THEN 1 END )
                  OVER ( PARTITION BY col1 ) AS has_ghi
         FROM   table1 t1
       ) t1
       INNER JOIN table2 t2
       ON ( t1.col3 = 'ABC' AND t2.abc = t1.col2 )
       OR ( t1.col3 = 'DEF' AND t2.def = t1.col2 )
       OR ( t1.col3 = 'GHI' AND t2.ghi = t1.col2 )
GROUP BY t1.col1, t2.col1, t1.has_ghi
HAVING COUNT( CASE t1.col3 WHEN 'ABC' THEN 1 END ) > 0
AND    COUNT( CASE t1.col3 WHEN 'DEF' THEN 1 END ) > 0
AND    ( COUNT( CASE t1.col3 WHEN 'GHI' THEN 1 END ) > 0 OR has_ghi = 0 )
ORDER BY t1.col1, t2.col1;

答案 1 :(得分:3)

另一种方法,计算加入所有可能的匹配后每个t1.col / t2.col组合的匹配数量:

select distinct t2_col1, t1_col1
from (
  select t2.col1 as t2_col1, t1.col1 as t1_col1, t1.ghi_count as t1_ghi_count,
    count(case when t1.col3 = 'ABC' then 1 end)
      over (partition by t1.col1, t2.col1) as abc_matches,
    count(case when t1.col3 = 'DEF' then 1 end)
      over (partition by t1.col1, t2.col1) as def_matches,
    count(case when t1.col3 = 'GHI' then 1 end)
      over (partition by t1.col1, t2.col1) as ghi_matches
  from (
    select t1.*,
      count(case when t1.col3 = 'GHI' then 1 end)
        over (partition by t1.col1) as ghi_count
    from table1 t1
  ) t1
  join table2 t2
  on (t1.col3 = 'ABC' and t2.abc = t1.col2)
  or (t1.col3 = 'DEF' and t2.def = t1.col2)
  or (t1.col3 = 'GHI' and t2.ghi = t1.col2)
)
where abc_matches > 0
and def_matches > 0
and (t1_ghi_count = 0 or ghi_matches > 0)
order by t1_col1, t2_col1;

您的样本数据包含:

T2_COL T1_COL
------ ------
A1     A     
A3     A     
A4     A     
A7     A     
A8     A     
A9     A     
A1     B     
A3     B     
A4     B     
A7     B     
A8     B     
A10    C     

不确定效率与MTO交叉加入与您的实际数据是否会有显着差异。