Sql 与公共表连接的并集

Sql 与公共表连接的并集,sql,database,Sql,Database,我有一个查询,目前看起来像这样(我将简化它以切中要害): 也就是说,我们有两种类型的细节可以在一个装运上,我需要找到所有满足给定条件的装运的两种类型的所有记录。(假设这两个细节表中有一些字段具有匹配的数据。在现实生活中,其中还有几个连接;正如我所说的,我正在尝试简化查询,以解决我今天要问的问题。) 但是“where”子句需要一个完整的文件扫描,所以做两次完整的文件扫描是非常低效的。从逻辑上讲,数据库引擎应该能够找到一次满足条件的装运记录,然后从type1detail和type2detail中找到

我有一个查询,目前看起来像这样(我将简化它以切中要害):

也就是说,我们有两种类型的细节可以在一个装运上,我需要找到所有满足给定条件的装运的两种类型的所有记录。(假设这两个细节表中有一些字段具有匹配的数据。在现实生活中,其中还有几个连接;正如我所说的,我正在尝试简化查询,以解决我今天要问的问题。)

但是“where”子句需要一个完整的文件扫描,所以做两次完整的文件扫描是非常低效的。从逻辑上讲,数据库引擎应该能够找到一次满足条件的装运记录,然后从type1detail和type2detail中找到shipmentid与这些值匹配的所有记录

但在SQL中我该怎么说呢

select shipment.f1, detail.f2
from shipment
join
(select shipmentid, f2
from type1detail
union
selection shipmdentid, f2
from type2detail
) d using (shipmentid)
where shipment.otherinfo='foo'
需要对type1detail进行完整的文件扫描,并与type2detail进行完整的文件扫描,然后将其加入到装运中,这比两次读取装运更糟糕。(因为每个明细表都大于装运。)

这似乎是一件很简单的事情,但我想不出我能表达它的方式


如果您知道该引擎的特定解决方案,我将使用Postgres,但我希望使用通用SQL解决方案。

我将使用临时表将shipmentid转储到与您的“otherinfo”where子句匹配的目录中。然后在联接中使用该临时表(不替换任何现有联接,而是添加另一个联接),以便联接条件仅使用ShipmentId,并且不需要where子句(除非您还对不在装运表中的列进行筛选,但关键是您仍然只扫描该表一次).

如果您经常运行此查询,则最好为otherinfo列编制索引,以避免完全扫描。我对博士后工作不多,但看起来至少有一个是绝对正确的,这将是解决眼前问题的一个体面的解决方案。(这不是全文搜索,而是一个简单的字段等于测试。)但一旦我看到这个问题,我开始更全面地思考。虽然一个新的索引可以解决这个问题,(a)我们公司的结构方式,我不可能在下一个版本中做到这一点,(b)它提出了许多其他假设情况。好吧,我希望有一个更漂亮的解决方案,但我认为这实际上是正确的答案。(如果这听起来不像是一个令人振奋的代言,那很抱歉。这让我想起了我认识的一个男人告诉一个女人她“不是没有吸引力”。所以我说,“哇,吉姆,这真是一个令人振奋的补充。当你这样奉承女人时,你一定会让女人俯首称臣。”)
select shipment.f1, detail.f2
from shipment
join
(select shipmentid, f2
from type1detail
union
selection shipmdentid, f2
from type2detail
) d using (shipmentid)
where shipment.otherinfo='foo'