想象一下以下场景:
有3个表A,B和C.
在表B和表C中,可以有多个项共享相同的外键值。
如您所见,C中的项目间接引用A 到 B.
我想要的是从A中获取所有在C中引用但在结果表中没有来自B或C的任何信息但没有重复的条目。
这甚至可能吗?
我试过这样,但不知道它是否正确:
select tableA.*
from tableA,
(select distinct tableB.AId as Aid
from tableB left join tableC on tableC.BId = tableB.id
group by tableB.id)
as temp
where tableA.id = temp.Aid
答案 0 :(得分:3)
我不确定我是否理解正确,但您可以试试这个:
SELECT DISTINCT `A`.`id`, `A`.`value1`, `A`.`value2` FROM `A`
INNER JOIN `B` ON `B`.`id-a` = `A`.`id`
INNER JOIN `C` ON `C`.`id-b` = `B`.`id`
如果表C上有一个键与表B相关,并且表A上有相应的外键,则返回表A中的所有值
答案 1 :(得分:0)
Masoud的良好反应的另一种方法是使用exists
作为相关子查询。
以下子查询以相关的方式将B连接到C(注意B.IDA到A.ID,A在子查询之外)。
如果我们假设数据库设计良好,那么A将不会有重复记录,因此我们可以省略一个不同的,因为我们没有将A连接到其他表。相反,我们只是检查是否存在" A"记录在B表中,由于内部连接,它必须在C表中有记录。这对性能有两个好处
它不必将所有记录加在一起 需要一个独特的;因此,你不会受到影响 截然不同。
它可以早日逃脱。一旦找到A的关键值 子查询(B到C加入),它可以停止查看,因此不必将所有B加入到所有A中。
我们选择" 1"在子查询中,我们不关心我们选择的内容,因为该值不会在任何地方使用。我们只是使用A的着色来(B JOIN C)来确定要显示的A中的内容。
SELECT A.*
FROM A
WHERE EXISTS( SELECT 1
FROM C
INNER JOIN B
on C.IDB = B.ID)
AND B.IDA = A.ID)
采取你的尝试并审查它:
select tableA.*
from tableA,
(select distinct tableB.AId as Aid
from tableB left join tableC on tableC.BId = tableB.id
group by tableB.id)
as temp
where tableA.id = temp.Aid
从" FROM"
开始你有tableA,(子查询)temp。这是一个CROSS JOIN,意味着A中的所有记录都将连接到(B JOIN C)的所有记录,因此如果A中有1000条记录,临时结果中有1000条记录,那么您将告诉数据库引擎生成结果集中有1000 * 1000条记录;然后被过滤,只包括在temp和A中匹配的记录。引擎可能足够智能以避免交叉连接并优化查询,但我发现它很难维护。所以我会改写为
SELECT tableA.*
FROM tableA
INNER JOIN (SELECT distinct tableB.AId as Aid
FROM tableB left join tableC on tableC.BId = tableB.id
GROUP BY tableB.id) as temp
ON tableA.id = temp.Aid
查看子查询(临时)
我们不需要一个小组,因为我们没有聚合。独特的确将我们降到了1个记录,但却以执行时间为代价。
所以我会重写这个:
SELECT tableA.*
FROM tableA
INNER JOIN (SELECT distinct tableB.AId as Aid
FROM tableB
LEFT JOIN tableC
on tableC.BId = tableB.id) as temp
ON tableA.id = temp.Aid
然后看整体,如果我们将外部查询连接更改为temp并使其成为存在...使用着色我们不会有连接的性能损失,也不会有明显的性能。并且我将左连接切换到内部,因为我们只需要C和B中的记录,所以如果我们将它保留为" LEFT JOIN"我们在B中有空值。这对我们没用。
这让我得到了我最初提供的答案。
SELECT tableA.*
FROM tableA
WHERE EXISTS (SELECT 1
FROM tableB
INNER JOIN tableC
on tableC.BId = tableB.id
AND tableB.AID = A.ID) as temp