如果我有两张桌子:
+-----------------+
+ people |
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | Joe | 42 |
| 2 | Sue | 30 |
+----+------+-----+
+-------------------+
+ employees |
+----+------+-------+
| id | dept | hired |
+----+------+-------+
| 1 | HR | 2015 |
| 2 | Dev | 2013 |
+----+------+-------+
我查询的是这样的人:
SELECT * FROM employees JOIN people ON employees.id=people.id WHERE id=2;
为什么会抛出错误?我知道id
并不是唯一的,但我强迫它是 common ,因为它必须由JOIN
共享。我也知道我可以通过询问SELECT *,people.id AS id FROM...
来绕过这一点,但这是一个理论问题,而不是寻找解决方案。
这只是MySQL没有得到足够开发的情况吗?或者是否有正当理由抛出此错误?
答案 0 :(得分:1)
您在想的是将连接的表视为一个,并且在该视图中有一个id
列。 MySQL可以通过使用子选择和自然连接来容纳该视图。
SELECT * FROM (SELECT * FROM employees NATURAL JOIN people) AS t2 WHERE id=2;
这会折叠所有公共列,同时也将它们用作连接的条件。返回的列将按公共列的顺序排列,其余列将构成第一个表,其余列将来自第二个表。在公共列中,如果有多个,它们的顺序将与它们在第一个表中的顺序相同,即使它们在第二个表中具有不同的顺序。
这允许您在脑海中查看数据时从MySQL中实现逻辑。
警告,如果有多个公共列,结果可能不是您所期望的。然后,连接将强制每列匹配,然后才将它们视为“匹配”。如果列组合形成一个键,那么这是预期的行为。但是,如果恰好有两个列具有相同的名称,但不同的用法不属于该键,则最终可能会出现一个空集。
答案 1 :(得分:0)
由于您使用的是WHERE
,因此不仅仅是您在FROM
之后放置的表格的过滤器。它将过滤这些表的结果。
你想做的事情甚至对人类来说都是模糊的。查询可能比您使用的示例更复杂。根据你的想法,阅读调试可能会更难。
同样在WHERE
之后按表格选择将为您提供更大的灵活性。例如,您可以使用WHERE employees.id=people.id
。
如何在PHP之类的内容中使用这些类型的查询?您正在使用SELECT * FROM
,您希望通过PHP内的$ row [' id']获得什么?
这种选择有利于更清晰的查询和更大的灵活性,并解决了机器和人类的歧义。
答案 2 :(得分:0)
最简单的答案是,当查询多个表时,MySQL期望field
子句中的table.field
时,只提供WHERE
引用就像尝试登录系统一样没有提供您的用户名,只提供您的密码。抱歉,当您要登录时,您必须告诉系统您提供的密码。Key + Datum = result.
Null + Datum = Error.
更深入一点,MySQL不会在JOIN语句 UNTIL THE QUERY FINISHES 中定义的两个表之间建立连接。 WHERE
子句按顺序处理,以确保表在连接时进行过滤。如果您想要搜索特定ID#的两个表,那么您需要为其添加语法。类似的东西:
`SELECT * FROM employees FULL JOIN people ON employees.id=people.id WHERE (employee.id = 2 OR people.id = 2)`
这是不同的,当一个或另一个表在公共表中没有匹配时,FULL JOIN仍然有效,它仍然会添加到结果中,缺少的条目的空列为NULL。
在各种类型的JOIN中有很多,包括this SO post,而even older SO post是http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_RestoreFromSnapshot.html的骗局,可以更详细地解释这一点。
TL:DR - 如果你使用一个表,MySQL知道在哪里看。当您使用多个表时,MySQL很容易混淆,需要确定您正在使用哪个表。这就是为什么它会向你抛出错误。修复很简单,您只需要在WHERE子句中向查询中添加两个内容,例如:
'SELECT * FROM employees LEFT JOIN people ON employees.id=people.id WHERE employee.id = 2'
将LEFT添加到JOIN为服务器提供了额外的指令,说明组合资产和将表名添加到列名称的方式将告诉MySQL需要查看哪个表。