【问题标题】:MySQL joining tables with joinMySQL 使用 join 连接表
【发布时间】:2013-01-14 16:21:58
【问题描述】:

我整天都在为这个问题摸不着头脑,只是无法解决。这是我第一次尝试使用 SQL Joining,虽然我们确实学到了一些基础知识,但我更倾向于深入研究高级内容。

基本上我正在制作自己的论坛,并且有两张桌子。 f_topics(线程)和 f_groups(论坛或类别)。 f_topics 中的 topicBase 和 f_groups 中的 groupID 之间存在关系,这表明每个主题属于哪个组。每个主题都有一个唯一的 ID,称为 topicID,组的 ID 相同,称为 groupID。

基本上,我试图将所有这些列放入一个 SELECT 语句中 - 主题的标题、主题发布的日期、主题所属的组的 ID 以及该组的名称。这是我尝试使用的,但组总是返回为 1,即使主题在 groupID 2 中:

$query=mysqli_query($link, "

SELECT `topicName`, `topicDate`, `groupName`, `groupID`
FROM `f_topics`
NATURAL JOIN `f_groups`
WHERE `f_topics`.`topicID`='$tid';


") or die("Failed to get topic detail E: ".mysqli_error());
var_dump(mysqli_fetch_assoc($query));

对不起,如果这没有多大意义,如果我的整个逻辑完全错误,如果是这样,你能建议一种替代方法吗?

感谢阅读!

【问题讨论】:

    标签: php mysql sql join web


    【解决方案1】:

    要连接表,您需要映射外键。假设您的组表有一个 groupID 字段,这就是您加入它们的方式:

    SELECT `topicName`, `topicDate`, `groupName`, `groupID`
    FROM `f_topics`
    LEFT JOIN `f_groups`
    ON `f_topics`.`groupID` = `f_groups`.`groupID`
    WHERE`f_topics`.`topicID`='$tid';
    

    【讨论】:

    • 不应该是... FROM `f_groups` LEFT JOIN `f_topics` ...吗?
    • 根据问题的要求,我不这么认为。
    • 我从一个主题属于一个组的问题中得出结论,而不是相反。通过建议您的左加入,您似乎假设一个主题可能属于一个不存在的组或根本不属于任何组。是这样吗?
    • 如果他们都被分配到一个组,没关系,查询会工作,是吗?
    • 是的,它会起作用,但是为什么不使用 inner 连接呢?我的意思是,乍一看,左连接确实表明(对我来说)不匹配是可能的/预期的,因此从维护的角度来看,这可能有点令人困惑。 (而且我在开始时实际上对您的意图感到困惑。)在性能方面,优化器可能会发现在这种特殊情况下左连接等同于内连接,但如果不是,则生成的查询计划可能会比优化器为内部连接生成的效率低。
    【解决方案2】:

    据我所知,f_topics 中有一个名为“topicBase”的列,它引用了 f_groups 表中的 groupID 列。

    基于该假设,您可以执行 INNER JOIN 或 LEFT JOIN。 INNER 要求两个表中都有条目,而 LEFT 要求 f_topics 中只有数据。

    SELECT
        f_topics.topicName,
        f_topics.topicDate
        f_groups.groupName
        f_groups.groupID
    FROM
        f_topics
    INNER JOIN
        f_groups
        ON
        f_topics.topicBase = f_groups.groupID
    WHERE
        f_topics.topicID = '$tid'
    

    【讨论】:

      【解决方案3】:

      我建议您避免使用NATURAL JOIN

      主要是因为在引用表中添加新列可能会破坏工作查询,该列与另一个引用表中的列名匹配。

      其次,对于 SQL 的任何读者(审阅者)来说,在没有仔细审阅两个表的情况下,不清楚哪些列与哪些列匹配。 (而且,如果有人添加了一个破坏查询的列,那么在添加该列之前就更难弄清楚过去的 JOIN 标准是什么。


      相反,我建议您在 ON 子句的谓词中指定列名。

      最好通过表名或较短的表别名来限定所有列引用。

      对于更简单的陈述,我同意这可能看起来像不必要的开销。但是一旦语句变得更加复杂,这种模式会极大地提高语句的可读性。

      如果没有这两个表的定义,我将不得不做出假设,并且我“猜测”这两个表中都有一个 groupID 列,这是唯一一个名为相同的。但是您指定它与f_groups 中的groupID 匹配的f_topics 中的topicBase 列。 (而 NATURAL JOIN 不会让你明白这一点。)

      我认为这个查询会返回你想要的结果集:

      SELECT t.`topicName`
           , t.`topicDate`
           , g.`groupName`
           , g.`groupID`
        FROM `f_topics` t
        JOIN `f_groups` g
          ON g.`groupID` = t.`topicBase`
       WHERE t.`topicID`='$tid';
      

      如果topicBase 列可能为 NULL 或包含与 f_groups.GroupID 值不匹配的值,并且您希望返回该主题,并且 f_group 中的列返回为 NULL(当没有匹配),您可以通过外连接获得。

      要获得该行为,在上面的查询中,在 JOIN 关键字之前添加 LEFT 关键字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多