两个表加入时自我加入

时间:2016-10-18 22:00:55

标签: sql self-join

我有2个表与父外键关系 表1 - (id1,pIntID,fid)id1-主键,fid外键 表2 - (fid,value)fid主键

值将是这样的 表1

id1, pIntID, fid
1    IR1     AC
2    IR1     RJ
3    IR2     AC
4    IR2     AC

表2

fid, value
AC   accept
RJ   reject

我必须从表一中选择那些tablle2.value = Accept但不是Reject的pIntID。我能够使用子查询来做到这一点,但是这会对大量数据造成严重影响,是否有最佳方法可以做到这一点?

这是工作查询:

select t1.pIntid
from table1 t1 join
     table2 t2
     on t1.fid = t2.fid
where t2.value = 'accept' and
      t1.pIntid not in (select tx1.pintid
                        from table1 tx1 join
                             table2.tx2
                             on tx1.fid = tx2.fid
                        where tx2.value = 'reject'
                       ) 

2 个答案:

答案 0 :(得分:0)

这可能有点扭曲,因为它在where子句中有约束,但我相信会起作用:

select t1.pintid
from table1 t1
join table2 t2 on t1.fid = t2.fid
where t2.value in ('accept', 'reject')
group by t1.pintid
having count(distinct t2.value) = 1
   and t2.value = 'accept'

另一个解决方案(我猜是更干净)会使用NOT EXISTS来排除那些包含pintidaccept状态的reject

select t1.pintid
from table1 t1
join table2 t2 on t1.fid = t2.fid
where t2.value = 'accept'
  and not exists (
    select 1
    from table1 t1x
    join table2 t2x on t1x.fid = t2x.fid
    where t2x.value = 'reject'
      and t1.pintid = t1x.pintid
    )
group by t1.pintid

答案 1 :(得分:0)

作为另一种选择,您可以使用反连接模式。

 SELECT t1.pIntid
   FROM table1 t1
   JOIN table2 t2
     ON t2.fid   = t1.fid
    AND t2.value = 'accept'
   LEFT
   JOIN table2 tx2
     ON tx2.fid   = t1.fid
    AND tx2.value = 'reject'
  WHERE tx2.fid IS NULL

反连接模式是外连接,WHERE子句中的条件排除了找到匹配项的行。

为获得最佳性能,我们希望在table2上提供适当的覆盖索引。将fidvalue作为索引中的前导列。

如果table2中有多行,其值为'则接受'对于相同的fid,则连接操作将产生"重复"行。