【问题标题】:How to join all three tables in MYSQL?如何在 MYSQL 中连接所有三个表?
【发布时间】:2016-11-19 15:30:12
【问题描述】:

我有一个 MySQL 数据库,其中包含三个表,其中包含有关用户上传照片的信息。我有一个 PHP 页面,显示数据库中的所有照片 (tbl_uploads) 以及上传照片的人 (tbl_users)。为了显示照片和上传照片的人,我加入了 MySQL 查询。

SELECT * 
FROM tbl_uploads, tbl_users
WHERE tbl_uploads.user_id = tbl_users.user_id
ORDER BY date DESC

我现在想将第三个表 tbl_collab 加入到 MySQL 查询中,该查询允许我显示与照片协作的所有用户(一个表单允许他们将 $file 和他们的 $user_id 发布到 @ 987654328@)。我想我需要从tbl_uploads.filetbl_collab.user_id 添加一个联接,但我不确定如何。

tbl_users
|//**user_id**//|int(11)|No|
|user_name|varchar(25)|No|
|user_email|varchar(60)|No|
|user_password|varchar(255)|No|
|joining_date|datetime|No|

tbl_uploads

|//**id**//|int(10)|No|
|file|varchar(100)|No|
|type|varchar(30)|No|
|size|int(11)|No|
|user_id|int(11)|No|
|user_name|varchar(25)|No|

 tbl_collab

|//**id**//|int(11)|No|
|user_name|varchar(100)|No|
|user_id|int(11)|No|
|file|varchar(255)|No|

我一直在尝试您的各种建议,但我无法真正让它们像我希望的那样发挥作用,所以我提出了一个 mysql fiddle 可能对我有所帮助。 问题是,当我遍历查询在 PHP 中抛出的行时,我只得到与 tbl_uploads.file and tbl.collab.file 连接的行,或者我得到多行重复。

【问题讨论】:

  • 使用显式连接语法 (join / on ) 而不是表名在 from 子句中用逗号分隔。在工作面试/代码审查中看起来不会那么热

标签: php mysql sql select join


【解决方案1】:

我建议对连接使用 ANSI SQL 语法(而不是在“from”子句中提及多个表),因为一旦查询变得复杂,我发现 ANSI 语法更容易遵循。使用该语法,连接多个表没什么大不了的。例如,

SELECT uploads.<column>, users.<column>, collabs.<column> 
FROM tbl_uploads uploads
JOIN tbl_users users ON users.user_id=uploads.user_id
JOIN tbl_collabs collabs ON collabs.file=uploads.file
ORDER BY uploads.date DESC

(注意,将上面的 &lt;column&gt; 替换为您要从相应表中选择的列的名称,必要时使用 AS 语法提供唯一名称。)

如果您预计数据库会变得很大,请考虑您可能希望在连接条件中的字段上创建索引以提高性能。您可能还想在加入时使用左联接,例如,tbl_collabs 如果上传可能没有协作者,否则如果tbl_collabs 中没有匹配的行,则查询将不返回任何数据。

【讨论】:

  • 避免使用 .* 符号。出于很多原因。一种是常见的列名。需要明确的是,您是这里唯一一个从 多个 表中选择列列表的人,并且列名冲突
  • @Drew 同意...我正在拍摄与用户原始查询等效的内容,但没有看到 tbl_collabs 和 tbl_users 之间的冲突。
  • 干得好。没有理由因为我而扼杀你的答案。这是我的支持。欢迎来到堆栈。
  • 谢谢。长期潜伏者,但现在已经过了开始贡献的时间了。 :-)
【解决方案2】:

首先要做的是规范化您的数据。如果您仔细观察,用户名会出现在所有三个表中。它不应该。它只属于 users 表。那么你的其他表需要有一个 user_id 字段而不是用户名。

tbl_uploads

|//**id**//|int(10)|No|
|file|varchar(100)|No|
|type|varchar(30)|No|
|size|int(11)|No|
|user_id|int(11)|No|

 tbl_collab

|//**id**//|int(11)|No|
|user_id|int(11)|No|
|file|varchar(255)|No|

在这两种情况下,user_id 都是用户表中id 字段的外键。现在我们有一些一致的东西可以加入。

SELECT * FROM tbl_uploads
  INNER JOIN tbl_users ON tbl_uploads.user_id = tbl_users.user_id
  INNER JOIN tbl_collab ON tbl_collab.file = tbl_uploads.file

您应该使用 INNER JOIN 还是 LEFT JOIN 取决于您需要对数据执行什么操作,但根据提供的信息,INNER JOIN 似乎更合适。

更新:正如@drew 指出的那样,您的所有表都没有名为date 的列,您是否打算按tbl_users.joining_date 排序?

【讨论】:

  • 感谢所有答案,真的很有帮助,我正在仔细阅读它们以准确理解它们。
【解决方案3】:

似乎加入对我来说是存档

  SELECT * 
  FROM tbl_uploads
  inner join tbl_users on  tbl_uploads.user_id = tbl_users.user_id
  inner join tbl_collab  on tbl_collab.file = tbl_uploads.file
  ORDER BY date DESC

【讨论】:

    【解决方案4】:

    您可以添加另一个连接条件。另外,请注意隐式连接(在 from 子句中有多个表)不是一个好的做法,您可能应该使用显式的 join 子句:

    SELECT   * 
    FROM     tbl_uploads up
    JOIN     tbl_users us ON up.user_id = us.user_id
    JOIN     tbl_collab c ON c.user_id = up.user_id
    ORDER BY date DESC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多