为啥这种“嵌套连接”适用于 PDO 而不适用于 MySql cli?

Posted

技术标签:

【中文标题】为啥这种“嵌套连接”适用于 PDO 而不适用于 MySql cli?【英文标题】:Why does this "nested join" works with PDO but not with MySql cli?为什么这种“嵌套连接”适用于 PDO 而不适用于 MySql cli? 【发布时间】:2019-01-08 15:11:54 【问题描述】:

我不明白为什么这个查询有效以及它的实际含义。应该注意的是,这个查询在使用 PDO 时有效,但不能通过 mysql cli 甚至 phpmyadmin。

   SELECT table1.something, table2.something 
   FROM someTable
   LEFT JOIN table 1
     INNER JOIN table2
       ON table2.table1_id = table1.id
     ON table1.account_id = someTable.account_id

没有抛出错误,更奇怪的是,我实际上得到的结果与查询应该做的事情是一致的。

【问题讨论】:

SQL 查询永远不会以 LEFT JOIN 开头。请向我们展示您正在运行的实际完整查询。 加入...开启...加入...开启 如果这是整个查询,它不会在我知道的任何环境中工作。因为您声称它在某处有效,所以我将您的问题解释为关于 FROM 子句的子集。你应该澄清一下。 根据您的要求更改查询。我已经为您省去了其他连接和选择。 【参考方案1】:

这是有效的 SQL 语法,假设您刚刚从 FROM 子句中获取了一个 sn-p。解释为:

SELECT table1.something, table2.something
FROM someTable
LEFT JOIN
(table1 INNER JOIN
 table2 bbm
 ON table2.table1_id = table1.id
)
ON table1.account_id = table2.account_id

也就是说,这真的很神秘,因为别名将table2 重命名为bbm,这并没有被使用。 ON 条件仅指较早的表。结果是CROSS JOIN 的某种奇怪形式。

以这种方式嵌套JOINs 应该——在我看来——仅仅被视为一种娱乐。不要嵌套JOINs。在下一个表/子查询引用之前,每个 JOIN 后面都应该有它自己的 ON 子句。嵌套连接使代码更难理解。它可能会引入错误(我认为在这种情况下会发生)。也可能存在一些微妙的边缘情况,很难弄清楚发生了什么。

【讨论】:

这在 MySQL 中真的有效吗?如果没有选择列表,任何 API 如何工作? @TimBiegeleisen,很久以前,SQL 标准实际上允许类似于上面的查询,即tablename1 join tablename2 on ... - 没有选择列表。 (后来被删除了。) 虽然原始查询中有一个 from 。我刚刚隔离了导致查询错误的部分。现在已编辑。戈登,你能根据我的编辑你的吗?我添加了 select 和 from,最后一个 ON 子句在 someTable.account_id 而不是 table2.account_id 上。很抱歉给您带来不便。 无论如何,谢谢您的回答,当我弄清楚这是否真的是这样时,我会验证它。知道为什么这适用于 PDO 但不适用于 MySql cli 吗?这是最困扰我的事情。 当我在不修改数据的情况下使用此语法时,查询现在可以在 phmyadmin 中使用。我正在等着看是否有人知道为什么这仅在 PDO 上有效,然后再接受您的答案以获得完整的答案。【参考方案2】:

标准 SQL 中有两种用于编写多个连接的语法变体,常见的一种:

a join b on ... join c on ... join d on ...

还有一个奇怪的:

a join b join c join d on ... on ... on ...

在这两种情况下,首先处理第一个ON,这意味着奇怪的语法将最后一个ON中的第一个表和第一个ON中的最后一个表连接起来,这真的很难理解。这就是为什么几乎没有人使用它(但有些工具可能会创建它)

改变你的陌生

SELECT table1.something, table2.something 
FROM someTable
LEFT JOIN table1
  INNER JOIN table2 bbm
  ON table2.table1_id = table1.id
ON table1.account_id = someTable.account_id

在第一次加入后将最后一个 ON 移到共同点:

SELECT table1.something, table2.something 
FROM someTable
LEFT JOIN table1
  ON table1.account_id = someTable.account_id
INNER JOIN table2 bbm
  ON table2.table1_id = table1.id

【讨论】:

以上是关于为啥这种“嵌套连接”适用于 PDO 而不适用于 MySql cli?的主要内容,如果未能解决你的问题,请参考以下文章

为啥装饰器模式适用于指针而不适用于引用?

为啥 Slime 检查仅适用于鼠标单击而不适用于键盘命令?

为啥 Laravel 中间件适用于单个路由而不适用于一组路由

为啥 viewPager 的 setCurrentItem() 适用于下一页而不适用于上一页?

CreateProcess 适用于某些计算机,而不适用于其他计算机。为啥?

为啥我的 Button 样式对象仅适用于按钮内的文本,而不适用于整个按钮?