使用SQL,如何在单个表多对多关系中查找不匹配项?
我有一个数据库,其中包括记录成分之间反应的结果。它目前由以下三个表构成:使用SQL,如何在单个表多对多关系中查找不匹配项?,sql,many-to-many,self-join,Sql,Many To Many,Self Join,我有一个数据库,其中包括记录成分之间反应的结果。它目前由以下三个表构成: | Material | |----------------| | id : Integer | | name : Varchar | | Reaction | |-----------------| | id : Integer | | <other details> | | Ingredient | |----------------------
| Material |
|----------------|
| id : Integer |
| name : Varchar |
| Reaction |
|-----------------|
| id : Integer |
| <other details> |
| Ingredient |
|-----------------------|
| material_id : Integer |
| reaction_id : Integer |
| quantity : Real |
|材料|
|----------------|
|id:整数|
|姓名:Varchar|
|反应|
|-----------------|
|id:整数|
| |
|配料|
|-----------------------|
|物料标识:整数|
|反应id:整数|
|数量:真实|
这映射了材料和反应之间的多对多关系
我想运行一个查询,返回每一对没有形成反应的材料。(也就是说,每对(x,y)都不存在完全使用x和y的反应,也不存在其他材料。)在其他情况下,我会在中间表上进行左连接,然后查找NULLreaction\u id
s。在本例中,我通过对materials表和它本身进行交叉连接来获得对,但我不确定如何(或是否)对两个材质别名进行两次左连接
如何做到这一点
我最感兴趣的是一种通用的SQL方法,但我目前正在使用SQLite3和SQLAlchemy。我可以选择将数据库移动到PostgreSQL,但强烈建议使用SQLite。使用交叉连接来生成列表,然后删除处于相同反应中的对
select m.id, m2.id as id2
from materials m cross join
materials m2
where not exists (select 1
from ingredient i join
ingredient i2
on i.reaction_id = i2.reaction_id and
i.material_id = m.id and
i2.material_id = m2.id
);
虽然这个查询看起来很复杂,但它本质上是对您的问题的直接翻译。where
条款是说,对于同一反应,没有两种成分具有每种材料
对于性能,您需要一个关于成分(反应id、材料id)
的索引
编辑:
如果愿意,您可以在不存在的情况下使用左连接和where
执行此操作:
select m.id, m2.id
from materials m cross join
materials m2 left join
ingredients i
on i.material_id = m.id left join
ingredients i2
on i2.material_id = m2.id and
i2.reaction_id = m2.reaction_id
where i2.reaction_id is null;