我在我正在编写的程序的生命周期中测试了相当多的子查询变体。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
)
EDIT:随着需求的变化(更多过滤),很多都发生了变化,所以我想我会更新它。我标记为的构造XXXX
在我的示例中包含一个左连接(其中主表到辅助表的关系是1-*
)并且出现得相对较快。
这是上下文有助于理解问题的地方:
- 初始要求:全部拉取
vendors
, 没有财务记录 3
表。
- 附加要求:也根据替代方案排除
payers
(1-*
关系)。这就是上面例子的基础。
- 更多要求:也根据替代方案排除
payee
(*-*
之间的关系payer
and payee
).
多对多连接呈指数增加了我标记的构造中的记录计数XXXX
,这反过来又产生了很多不必要的工作。例如:一个客户有 3 个payers
, and 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