内连接返回重复行

3

我有以下表结构,并在每个表中包含了主键和外键:

CREATE TABLE `Table1` (
`Table1_ID` int(6) ,
`Table2_FK` int(6) ,
 **Other Fields***
) 

CREATE TABLE `Table2` (
`Table2_ID` int(6) ,
`Table3_FK` int(11),
 **Other Fields***
) 
CREATE TABLE `Table3` (
`Table3_ID` int(6) ,
`Table2_FK` int(11),
 **Other Fields***
) 

CREATE TABLE `Table4` (
`Table4_ID` int(6) ,
`Table3_FK` int(11),
 **Other Fields***
) 

CREATE TABLE `Table5` (
`Table5_ID` int(6) ,
`Table4_FK` int(6),
 **Other Fields***
) 

我已经设置了以下外键:

 ALTER TABLE `Table5`
 ADD CONSTRAINT `table5_ibfk_4` FOREIGN KEY (`Table4_FK `) REFERENCES   `Table4` (`Table4_ID`);

 ALTER TABLE `Table4`
 ADD CONSTRAINT `table4_ibfk_3` FOREIGN KEY (`Table3_FK `) REFERENCES `Table3` (`Table3_ID`);

 ALTER TABLE `Table1`
ADD CONSTRAINT `table1_ibfk_2` FOREIGN KEY (`Table2_FK `) REFERENCES     `Table2` (`Table2_ID `);

 ALTER TABLE `Table2`
 ADD CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`Table3_FK`) REFERENCES `Table3` (`Table3_ID `);

我的问题是当我运行以下INNER JOIN查询时:

 SELECT *
 FROM `Table1 `
 INNER JOIN `Table2` ON `Table1`.`Table2_FK` =`Table2`.`Table2_ID` 
 INNER JOIN `Table3` ON `Table2`.`Table3_FK` = `Table3`.`Table3_ID` 
 INNER JOIN `Table4` ON `Table3`.`Table3_ID` = `Table4`.`Table3_FK ` 
 INNER JOIN `Table5` ON `Table4`.`Table4_ID` = `Table5`.`Table4_FK ` 
 WHERE (`Table1`.`Table1_ID ` ='43');

我期望返回两行记录,因为只有两个ID为43的记录,正如“WHERE”子句中所述。但实际上会返回8个ID为43的记录,我原以为内连接只会返回真实存在的结果,而不是所有结果。 更新: 当前数据如下:
INSERT INTO `Table1` (`Table1_ID `, `OtherData`, `Table2_FK `, `OtherData2`, `Date`) VALUES
(42, 1, 1, 'New', '2015-03-10 17:41:50'),
(43, 1, 1, 'New', '2015-03-10 17:44:35'),
(44, 1, 1, 'New', '2015-03-10 17:50:34'),
(45, 1, 1, 'New', '2015-03-10 17:55:20'),
(46, 1, 1, 'New', '2015-03-10 18:10:47');

INSERT INTO `Table2` (`Table2_ID `, `OtherData3`, `OtherData4 `,     `OtherData5`, `OtherData6`) VALUES
(1, 'blahtype', NULL, 1, '2015-03-13 00:00:00');

INSERT INTO `Table3` (`Table3_ID `, `Table2_FK `, `OtherData6`) VALUES
(1, 1, 'blahname');

INSERT INTO `Table4` (`Table4_ID`, `Table3_FK `, `OtherData6`, `OtherData7`,     `OtherData7`) VALUES
(2, 1, 'blahfieldname', 'blahcont', 'blahtype'),
(3, 1, 'blahfieldname2', 'blahcont', 'blahtype');

INSERT INTO `Table5` (`Table5_ID `, `OtherData`, `Table4_FK`, `OtherData`) VALUES
(1, 'test2', 2, 42),
(2, 'test3', 3, 42),
(3, 'Test4', 2, 43),
(4, 'test5', 3, 43),
(5, 'test6', 2, 44),
(6, 'test7', 3, 44),
(9, 'test8', 2, 78),
(10, 'test9',3, 78);

当前输出结果为:

 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |2|1| blahfieldname | blahcont | blahtype |1|test2|2|42
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |2|1| blahfieldname | blahcont | blahtype |3|test3|2|43
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |2|1| blahfieldname | blahcont | blahtype |5|test4|2|44
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |2|1| blahfieldname | blahcont | blahtype |9|test5|2|78
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |3|1| blahfieldname2| blahcont | blahtype |2|test6|3|42
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |3|1| blahfieldname2| blahcont | blahtype |4|test7|3|43
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |3|1| blahfieldname2| blahcont | blahtype |6|test8|3|44
 |43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |3|1| blahfieldname2| blahcont | blahtype |10|test9|3|78

预期输出为:

|43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |2|1| blahfieldname | blahcont | blahtype |3|test3|2|43
|43|1|1|New|2015-03-10 17:44:35|1| blahtype |NULL|1|2015-03-13 00:00:00|1|1| blahname |3|1| blahfieldname2| blahcont | blahtype |4|test7|3|43

1
表格数据,当前结果和期望结果,请! - jarlh
2
内连接还是左连接?请确保。 - Sarz
那是一个打错字,它是一个内连接,我已经编辑了代码以反映这一点。我还包括了所请求的数据。 - serverNewbie
2个回答

1
你说在table1中有两个id为43的记录,但是这在table2、table3、table4和table5中都被引用了。最终,你会显示与这两行id为43的数据在table1中的每个关系。
table1
ID    name
1     T1-Firstrow
2     T1-Secondrow

table2
ID    FK    name
1     1     T2-Firstrow
2     1     T2-Secondrow
3     2     T2-Thirdrow

如果你从table1中选择ID = 1,但是在加入table2后,你仍然会得到两行结果。

编辑:

使用你提供的数据更新,在选择ID为43时:

table1 has 1 row matching
table2 has 1 row matching
table3 has 1 row matching
table4 has 2 rows matching
table5 has 8 rows matching

在table5表中,您有两个名为“otherdata”的列,但其中一个似乎是指向table1的外键。如果是这样,请使用以下方法:
SELECT *
 FROM `Table1 `
 INNER JOIN `Table2` ON `Table1`.`Table2_FK` =`Table2`.`Table2_ID` 
 INNER JOIN `Table3` ON `Table2`.`Table3_FK` = `Table3`.`Table3_ID` 
 INNER JOIN `Table4` ON `Table3`.`Table3_ID` = `Table4`.`Table3_FK` 
 INNER JOIN `Table5` ON `Table4`.`Table4_ID` = `Table5`.`Table4_FK` AND 
                        `Table5`.`OtherDataFK` = `Table1`.`Table1_ID`
 WHERE (`Table1`.`Table1_ID ` ='43');

在表1中,只有1行ID为43,但应该返回两个结果,因为在表4中有两条记录与43匹配。 - serverNewbie
但是table5与table4的两行有8个关系。如果你正在寻找一个“2行结果集”,那么跳过与table5的连接,就可以得到了! :) - Mackan
是的,你可以这样做 - 但现在你正在使用FK将其连接(因此有8个结果)。你似乎想要的是使用“otherdata”作为到table1的直接链接(虽然我不能确定)。 - Mackan
是的,正确的,我将otherdata字段作为外键添加到table1中,因为这样返回了我想要的结果。然后我认为这违背了关系数据库的目的,因此我想看看是否可以通过FK连接返回我期望的结果。 - serverNewbie
确实,这样做是违背了初衷。因此,你需要考虑设计本身,而不是寻找绕过设计的方法来达到你的期望。也许设计本身是没问题的,只是你的期望有误。 :) - Mackan
非常感谢您的帮助,我认为这次是因为我对数据库设计世界的新鲜感抱有期望 :) - serverNewbie

0

你说得没错,内连接只返回两边都匹配的结果。

然而,我这里没有看到任何主键。假设你只是没有提到它们,并且所有的外键都指向目标表中的主键,那么我们有Table2ID作为主键,Table3 ID作为主键,Table5 ID作为主键。你说Table1只有两条记录,其中ID = 43。

我假设Table4有多条记录,其ForeignKey等于Table3中具有与Table2中ID相等的外键的记录的ID,而这些记录的ID又等于Table1中外键的ID。

使用你刚编辑的数据,

Table 1返回第二条记录,即ID为43的记录。此记录在FK为1的情况下加入到Table2中的一条记录。此记录与Table3中的一条记录相连。这条记录与Table4中的两条记录都相连,因此现在我们有了2条记录。这两条记录与Table5中的table4 ID = Table 5 FK相连,每条记录都与Table5中的4条记录相连。

这样就得到了8条记录的结果集。

~编辑 这个表格总共有8条记录,你跳过了ID 10,我以为这个表格里有10条记录。另外,你的表格2缺少外键。


正确,'TableX_ID' 是每个表中的主键,您的假设是正确的。 - serverNewbie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接