首页 > 解决方案 > 选择多个字段不在子查询中的位置(不包括连接)

问题描述

我需要提取在存档表中没有历史记录的记录。需要在存档中检查 1 条记录的 2 个字段。

从技术意义上讲,我的要求是左侧连接,其中右侧为“空”(也称为排除连接),在abap openSQL 中通常是这样实现的(无论如何,对于我的场景):

Select * from xxxx            //xxxx is a result for a multiple table join
where xxxx~key not in         (select key from archive_table where [conditions] ) 
  and xxxx~foreign_key not in (select key from archive_table where [conditions] )

这 2 个字段还会针对另外 2 个表进行检查,因此这意味着总共有 6 个子查询。

我之前使用过的数据库引擎通常有一些方法来处理此类问题(例如排除连接或外部应用)。

对于这种特殊情况,我将尝试将 ABAP 逻辑与“所有条目”一起使用,但我仍然想知道是否可以使用子查询的结果来检查多个字段或使用另一种形式的不包括使用 SQL 的多个字段上的连接逻辑(不涉及应用程序服务器)。

标签: subqueryabapexistsopensql

解决方案


我已经在我正在制作的程序的生命周期中测试了很多子查询的变体。NOT EXISTS在某些情况下,使用基于 2 个键的多字段检查(下面的简化示例)来排除。性能可以接受(处理时间约为 5 秒),但是,当基于 1 个字段排除时,它明显慢于相同的查询。

Select * from xxxx            //xxxx is a result for a multiple table inner joins and 1 left join ( 1-* relation )
where NOT EXISTS  (
   select key from archive_table 
   where key = xxxx~key OR key = XXXX-foreign_key 
) 

编辑: 随着要求的变化(更多过滤)发生了很多变化,所以我想我会更新这个。我在示例中标记的构造XXXX包含一个左连接(主表到辅助表的关系是1-*),并且它看起来相对较快。

这是上下文有助于理解问题的地方:

  • 初始要求:全部拉取vendors,3张表中没有财务记录。
  • 附加要求:也排除基于替代 payers1-*关系)。这就是上面的例子所基于的。
  • 更多要求:也排除基于替代payee(和之间的*-*关系)。 payerpayee

多对多连接成倍地增加了我标记的构造中的记录数XXXX,这反过来又产生了很多不必要的工作。例如:具有 3payers和 3的单个客户payees生成 9 行,总共要检查 27 个字段(每行 3 个),而实际上只有 7 个唯一值。

在这一点上,将左连接表从主查询移动到子查询并拆分它们可以显着提高性能。比任何看起来更聪明的替代品。

select * from lfa1 inner join lfb1 
       where 
          ( lfa1~lifnr not in ( select lifnr from bsik where bsik~lifnr = lfa1~lifnr )
       and lfa1~lifnr not in ( select wyt3~lifnr from wyt3 inner join t024e on wyt3~ekorg = t024e~ekorg and wyt3~lifnr <> wyt3~lifn2
                                                        inner join bsik  on bsik~lifnr = wyt3~lifn2 where wyt3~lifnr = lfa1~lifnr and t024e~bukrs = lfb1~bukrs  )
       and lfa1~lifnr not in ( select lfza~lifnr from lfza inner join bsik  on bsik~lifnr = lfza~empfk where lfza~lifnr = lfa1~lifnr )
          )
           and [3 more sets of sub queries like the 3 above, just checking different tables].

我的结论

  • 当排除基于单个字段时,两者都not in/not exits工作。一种可能比另一种更好,具体取决于您使用的过滤器。
  • 当排除基于 2 个或更多字段并且您在主查询中没有多对多联接时,not exists ( select .. from table where id = a.id or id = b.id or... )似乎是最好的。
  • 当您的排除标准在主查询中实现多对多关系时,我建议您寻找一种最佳方式来实现多个子查询(即使每个键表组合都有一个子查询也会比带有 1 个好的子查询的多对多连接,看起来不错)。

无论如何,欢迎对此的任何其他见解。

EDIT2:虽然它有点离题,但考虑到我的问题是关于子查询的,我想我会发布更新。一年多后,我不得不重新审视我致力于扩展它的解决方案。我了解到正确排除加入工作。我只是在第一次实施它时失败了。

select header~key 
from headers left join items on headers~key = items~key
where items~key is null

推荐阅读