具有超过14个表的Oracle SQL XOR条件

时间:2018-09-14 01:46:57

标签: sql oracle

我对sql设计有疑问。

上下文: 我有一个名为t_master的表和其他13个表(为简单起见,我们称它们为a,b,c ...),需要对其进行比较。

逻辑:

  • t_master将与表'a'进行比较,其中t_master.gen_val = 值。
  • 如果t_master中存在记录,则检索t_master记录,否则检索“ a”记录。
  • 如果两个表(t_master和a)中都存在记录,则不需要检索记录-XOR条件
  • 与其余12个表重复此比较。

我对此有一些想法,首先使用WITH使用子查询非主表(a,b,c ...)以及它们各自的WHERE子句。 然后使用XOR语句检索记录。

类似

WITH a AS (SELECT ...),
b AS (SELECT ...) 

SELECT field1,field2...
FROM t_master FULL OUTER JOIN a FULL OUTER JOIN b FULL OUTER JOIN c...
ON t_master.gen_value = a.value
WHERE ((field1 = x OR field2 = y ) AND NOT (field1 = x AND field2 = y)) 
AND ....
.
.
.
.

看到我有13个需要完全外部联接的表,是否有更好的方法/设计来处理此问题? 否则,我将至少有2 * 13行WHERE子句,由于t_master有点像日志表,因此我不确定是否会影响性能。

**假设我无法更改任何架构。 目前,我不确定该SQL是否能正常工作,所以我希望有人可以为此指导我正确的方向。

从used_by_already的建议中更新:

这就是我想要做的(在添加更多表之前先比较2个表,但是我无法像从ATP_R.TBL_HI_HDR HI_HDR子查询中那样从NOT EXISTS获取值。 br /> 我该如何克服?

SELECT LOG_REPO.UNIQ_ID,
  LOG_REPO.REQUEST_PAYLOAD,
  LOG_REPO.GEN_VAL,
  LOG_REPO.CREATED_BY,
  TO_CHAR(LOG_REPO.CREATED_DT,'DD/MM/YYYY') AS CREATED_DT,
  HI_HDR.HI_NO R_VALUE,
  HI_HDR.CREATED_BY R_CREATED_BY,
  TO_CHAR(HI_HDR.CREATED_DT,'DD/MM/YYYY') AS R_CREATED_DT
FROM ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO JOIN ATP_R.TBL_HI_HDR HI_HDR ON LOG_REPO.GEN_VAL = HI_HDR.HI_NO
WHERE NOT EXISTS
  (SELECT NULL
  FROM ATP_R.TBL_HI_HDR HI_HDR
  WHERE LOG_REPO.GEN_VAL = HI_HDR.HI_NO
  )

UNION ALL

SELECT LOG_REPO.UNIQ_ID,
  LOG_REPO.REQUEST_PAYLOAD,
  LOG_REPO.GEN_VAL,
  LOG_REPO.CREATED_BY,
  TO_CHAR(LOG_REPO.CREATED_DT,'DD/MM/YYYY') AS CREATED_DT,
  HI_HDR.HI_NO R_VALUE,
  HI_HDR.CREATED_BY R_CREATED_BY,
  TO_CHAR(HI_HDR.CREATED_DT,'DD/MM/YYYY') AS R_CREATED_DT
FROM ATP_R.TBL_HI_HDR HI_HDR JOIN ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO ON HI_HDR.HI_NO = LOG_REPO.GEN_VAL
WHERE NOT EXISTS
  (SELECT NULL
  FROM ATP_COMMON.VW_CMN_LOG_GEN_REPO LOG_REPO
  WHERE HI_HDR.HI_NO = LOG_REPO.GEN_VAL
  ) 

1 个答案:

答案 0 :(得分:0)

用于排除所有匹配行的完整外部联接可能是一个昂贵的查询。您没有提供太多详细信息,但是也许使用NOT EXISTS会更简单,并且也许它会产生更好的解释计划。遵循这些原则。

select
        cola,colb,colc
from t_master m
where not exists (
      select  null from a where m.keycol = a.fk_to_m
      )
and not exists (
      select  null from b where m.keycol = b.fk_to_m
      )
and not exists (
      select  null from c where m.keycol = c.fk_to_m
      )
union all
    select 
        cola,colb,colc from a
    where not exists (
          select  null from t_master m where a.fk_to_m = m.keycol
          )
union all
    select 
        cola,colb,colc from b
    where not exists (
          select  null from t_master m where b.fk_to_m = m.keycol
          )
union all
    select 
        cola,colb,colc from c
    where not exists (
          select  null from t_master m where c.fk_to_m = m.keycol
          )

您可以合并13个a,b,c ...表以简化编码,但这可能效果不佳。