Mysql 如何连接3个表,每个表都有下一行的键
想象一下以下场景: 有3张表A、B和CMysql 如何连接3个表,每个表都有下一行的键,mysql,Mysql,想象一下以下场景: 有3张表A、B和C 表A不了解表B和表C 表B具有表a的外键 表C具有表B的外键 在表B和表C中,可以有多个项目共享相同的外键值 如您所见,C中的项目间接引用到A到B 我想要的是从A中获取在C中引用的所有条目,但在我的结果表中没有来自B或C的任何信息,也没有重复项 这可能吗 我试过这样做,但不知道是否正确: select tableA.* from tableA, (select distinct tableB.AId as Aid from tabl
- 表A不了解表B和表C
- 表B具有表a的外键
- 表C具有表B的外键
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
我不确定我是否理解正确,但你可以试试这个:
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中的所有值。我不确定我是否正确理解它,但您可以尝试以下方法:
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中的所有值Masoud良好响应的另一种方法是通过相关子查询使用
exists
下面的子查询以相关方式将B连接到C(注意B.IDA到a.ID,a在子查询之外)
如果我们假设数据库设计良好,那么A将不会有重复的记录,因此我们可以在这里省略distinct,因为我们没有将A连接到其他表。相反,我们只是检查B表中是否存在一条“A”记录,由于内部联接,该记录在C表中必须有一条记录。这对性能有两个好处
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”开始
您有一个表(子查询)temp。这是一个交叉连接,意味着a中的所有记录都将连接到(B JOIN C)的所有记录,因此如果a中有1000条记录,temp结果中有1000条记录,那么您将告诉数据库引擎在结果集中生成1000*1000条记录;该引擎可能足够聪明,可以避免交叉连接并优化查询,但我发现维护起来很混乱。所以我会重写为
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
查看子查询(temp)
我们不需要分组,因为我们没有聚合。distinct确实将我们的记录减少到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并使其成为exists。。。使用着色,我们没有连接的性能影响,也没有明显的效果。我会将左连接切换到一个内部连接,因为我们只需要C和B中的记录,所以如果我们将其作为“左连接”保留,则B中会有null,这对我们没有任何意义
这让我得到了我最初提供的答案
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
Masoud良好响应的另一种方法是通过相关子查询使用
exists
下面的子查询以相关方式将B连接到C(注意B.IDA到a.ID,a在子查询之外)
如果我们假设数据库设计良好,那么A将不会有重复的记录,因此我们可以在这里省略distinct,因为我们没有将A连接到其他表。相反,我们只是检查B表中是否存在一条“A”记录,由于内部联接,该记录在C表中必须有一条记录。这对性能有两个好处
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”开始
您有一个表(子查询)temp。这是一个交叉连接,意味着a中的所有记录都将连接到(B JOIN C)的所有记录,因此如果a中有1000条记录,temp结果中有1000条记录,那么您将告诉数据库引擎在结果集中生成1000*1000条记录;该引擎可能足够聪明,可以避免交叉连接并优化查询,但我发现维护起来很混乱。所以我会重写为
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
查看子查询(temp)
我们不需要分组,因为我们没有聚合。distinct确实将我们的记录减少到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并使其成为exists。。。使用着色,我们没有连接的性能影响,也没有明显的效果。我会将左连接切换到一个内部连接,因为我们只需要C和B中的记录,所以如果我们将其作为“左连接”保留,则B中会有null,这对我们没有任何意义
这让我得到了我最初提供的答案
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
如果您为表A、B、C提供一些示例数据,并基于这些示例数据生成您期望的输出,那将是非常棒的