Select 其中多个字段不在子查询中(不包括连接)

Select where multiple fields are not in subquery (excluding join)

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

在技术意义上,我的要求是左侧连接,右侧为 'null'(a.k.a。排除连接),在 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 个 table 进行检查,因此这意味着总共有 6 个子查询。

我以前用过的数据库引擎一般都有一些处理这类问题的方法(比如excluding join或者outer apply)

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

if it is possible to use results of a sub-query to check more than than 1 field or use another form of excluding join logic on multiple fields

不,不可能在子查询中检查两列,正如SAP Help明确指出的那样:

The clauses in the subquery subquery_clauses must constitute a scalar subquery.

Scalar 是这里的关键字,即它应该 return 正好是一列。

你的子查询可以有多列键,这样的语法是完全合法的:

SELECT  planetype, seatsmax
  FROM  saplane AS plane
 WHERE seatsmax < @wa-seatsmax AND
       seatsmax >= ALL ( SELECT  seatsocc
                           FROM  sflight
                           WHERE carrid = @wa-carrid AND
                                 connid = @wa-connid     )

但是你说这两个字段应该针对不同的表进行检查

Those 2 fields are also checked against two more tables

所以你不是这样的。您唯一的选择似乎是多连接。

P.S. FOR ALL ENTRIES不支持否定逻辑,你不能只使用某种NOT IN FOR ALL ENTRIES,它不会就这么简单。

我在我制作的程序的生命周期中测试了很多子查询的变体。 NOT EXISTS 在某些情况下,基于 2 个键进行排除的多字段检查(下面的简化示例)有效。 性能acceptable(处理时间约为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 的构造包含一个左连接(其中主要到次要的 table 关系是 1-* )并且它看起来相对较快。

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

  • 初始要求:全部拉取vendors,3年无财务记录 table秒。
  • 附加要求:也根据备选方案排除 payers1-*关系)。这是上面例子的基础。
  • 更多要求:还根据备选 payeepayerpayee 之间的 *-* 关系排除)。

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

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

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... ) 似乎是最好的。
  • 当您的排除条件在您的主查询中实现多对多关系时,我建议您寻找一种最佳方式来实现多个子查询(即使每个键都有一个子查询-table 组合将比具有 1 个好的子查询的多对多连接执行得更好,看起来不错)。

无论如何,欢迎对此有任何额外的见解。

EDIT2:虽然它有点偏离主题,但考虑到我的问题是关于子查询的,我想我会 post 更新。一年多后,我不得不重新审视我致力于扩展它的解决方案。我了解到正确排除连接有效。我第一次实施它时非常失败。

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