【问题标题】:Inner Join in ON ClauseON 子句的内连接
【发布时间】:2011-09-16 09:06:35
【问题描述】:

我有一个 MySQL 查询,它试图获取所有包含“word%”之类的数据的页面。我有一个名为 Pages2Data 的多对多表。看来要做到这一点,我需要有一个内连接将 Pages 连接到 Pages2Data 表,然后另一个内连接将 Pages2Data 连接到数据。

以下不起作用,因为嵌套的 SELECT 子句可以返回多行。我不确定如何解决它:

SELECT * FROM `Pages` 
   INNER JOIN `Pages2Data` ON 
      (`Pages2Data`.`DataID`=(SELECT `DataID` FROM `Data` WHERE `DataWord` LIKE 'word%'))
      AND `Pages`.`PageID`=`Pages2Data`.`PageID`;

【问题讨论】:

    标签: mysql sql join inner-join


    【解决方案1】:

    试试这个

    SELECT * FROM `Pages` p, `Pages2Data` p2d, `Data` d
    WHERE p.`PageID` = p2d.`PageID`
    AND p2d.`DataID` = d.`DataID`
    AND `DataWord` LIKE 'word%'
    

    【讨论】:

    • 虽然不知道SELECT * 会返回这个实例中想要的列
    • 哇,我也觉得愚蠢,因为没有发现这本来可以更简单。谢谢你看到它,JellyBelly。我想知道这是否是最佳顺序?或许 LIKE 语句应该放在 WHERE 子句的第一位,因为无论如何都需要运行它,并且它会缩小 ID 匹配需要完成的工作量。想法?
    • 我认为这无所谓! :D
    • 隐式语法在 1992 年被一种更好的语法所取代,这种语法更清晰、更易于维护并且不太可能因意外交叉连接而产生问题。没有理由在新代码中使用隐式连接,也不应该鼓励使用它。
    【解决方案2】:

    您可以在 where 子句中勾选“Like”。

    SELECT * FROM 
               `Pages` 
    INNER JOIN 
               `Pages2Data` ON  (`Pages`.`PageID`=`Pages2Data`.`PageID`)
    WHERE
                `DataWord` LIKE 'word%'
    

    【讨论】:

    • DataWord 位于名为 Data 的第三个表中,该表不在您的查询中。
    【解决方案3】:
    SELECT * FROM `Pages`     
    INNER JOIN `Pages2Data`
       ON `Pages`.`PageID`=`Pages2Data`.`PageID`
    INNER JOIN `Data` ON `Data`.`DataID`= `Pages2Data`.`DataID`
    WHERE `DataWord` LIKE 'word%'; 
    

    【讨论】:

    • 与上面没有内部连接的 JellyBelly 方法相比,这样做有优势吗?
    • 隐式连接不利于维护(等到您需要将左连接添加到另一个表并了解我的意思)并且更有可能出现错误,例如意外的交叉连接。它们在大约 20 年前被更好的语法所取代,没有任何情况(除了支持还没有语法的旧数据库)我想我会在哪里支持它们在新代码中使用。 where 子句与 join 的分离也使将来的意图更加清晰。
    • 有趣...我感谢您的解释!最后一个问题:在您的查询中,首先调用哪个子句? where 子句还是内连接?
    • 在 mysql 中我不知道,在 SQl Server 中它们会有相同的执行计划和相同的性能。
    • 理论上,JOIN 先完成(基于 ON 条件),然后应用 WHERE 条件。在实践中,实际数据库所做的是“编译”查询并提出有时复杂的优化计划,具体取决于表大小、可以使用的现有索引等。结果保证是相同的(除了可能是为了显示行的顺序)。
    【解决方案4】:
    SELECT *
    FROM Pages
       INNER JOIN Pages2Data
          ON Pages.PageID = Pages2Data.PageID
       INNER JOIN Data
          ON Pages2Data.DataID = Data.DataID
    WHERE DataWord LIKE 'word%'
    

    【讨论】:

      【解决方案5】:

      首先是您的查询的问题:

      1. 连接条件应该在 ON 子句旁边
      2. 最外层查询中没有 WHERE 子句

      固定查询:

      SELECT * FROM `Pages` 
      INNER JOIN `Pages2Data` ON `Pages`.`PageID`=`Pages2Data`.`PageID`
      WHERE `Pages2Data`.`DataID`= (SELECT `DataID` FROM `Data` WHERE `DataWord` LIKE 'word%');
      

      替代查询:

      SELECT `PG`.*
      FROM `Pages` `PG`
      INNER JOIN `Pages2Data` `PD` ON `PD`.`PageID` = `PG`.`PageID`
      INNER JOIN `Data` `DA` ON `PD`.`DataID` = `DA`.`DataID`
      WHERE `DA`.`DataWord` LIKE 'word%';
      

      【讨论】:

      • 你的第一个查询应该有:WHERE Pages2Data.DataID IN (SELECT ...
      • 是的,当然应该。我刚刚粘贴了原始查询并修复了问题。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-18
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多