无法使用JOIN MYSQL确定WHERE子句应该是什么

use*_*609 6 mysql sql database mysqli join

我一直在创建一个MySQL查询.贝娄是我的数据库结构.

作者(author_id和author_name)

书籍(book_id和book_title)

books_authors是链接表(book_id和author_id)

所有书籍和作者的结果 - http://i.stack.imgur.com/VLzXn.png

我需要为某位作者获取所有书籍,但如果一本书有2位作者,则必须同时显示第二本书.例如,book_id = 2的书"Good Omens"有两位作者.当我运行查询时,我得到了author_id = 1的书籍,但我不能在结果中包含第二作者 - "Neil Gaiman".查询是:

SELECT * FROM books 
   LEFT JOIN books_authors 
       ON books.book_id=books_authors.book_id 
   LEFT JOIN authors 
       ON books_authors.author_id=authors.author_id 
WHERE books_authors.author_id=1
Run Code Online (Sandbox Code Playgroud)

以下是结果:

http://i.stack.imgur.com/PypqZ.png

我希望你能理解我,任何帮助将不胜感激.

Fra*_*azz 5

您需要更改WHERE子句以执行如下的子选择:

SELECT b.*, a.*
FROM books b
LEFT JOIN books_authors ba ON ba.book_id  = b.book_id
LEFT JOIN authors       a  ON a.author_id = ba.author_id
WHERE b.book_id IN (
  SELECT book_id
  FROM books_authors
  WHERE author_id=1)
Run Code Online (Sandbox Code Playgroud)

您的查询的问题是WHERE子句不仅过滤您在结果集中获得的书籍,还过滤书籍 - 作者关联.

使用此子查询,您首先使用作者ID过滤书籍,然后使用这些书ID来获取所有关联的作者.

顺便说一句,我确实认为在这种特定情况下用INNER JOIN替换OUTER JOIN的建议应该适用.books_authors上的第一个LEFT OUTER JOIN肯定是无用的,因为WHERE子句保证该表中每个选定的book_id至少有一行.第二个LEFT OUTER JOIN 可能没用,因为我希望author_id是authors表的主键,我希望books_authors表在author_id上有一个外键和一个NOT NULL约束...这意味着你不应该有books_authors行,不引用特定作者行.

如果这是真的并且已经确认,那么查询应该是:

SELECT b.*, a.*
FROM books b
JOIN books_authors ba ON ba.book_id  = b.book_id
JOIN authors       a  ON a.author_id = ba.author_id
WHERE b.book_id IN (
  SELECT book_id
  FROM books_authors
  WHERE author_id=1)
Run Code Online (Sandbox Code Playgroud)

请注意,在大多数情况下,INNER JOIN可能比OUTER JOIN更有效(它们为引擎提供了更多关于如何执行stament和获取结果的选择).因此,如果不是绝对必要的话,你应该避免使用OUTER JOIN.

我添加了别名并从结果集中删除了冗余列.

  • 添加别名,因为它现在不明确(book_id在books和books_authors中),MySQL不喜欢它. (2认同)

Mar*_*ams 2

您不需要为此使用子查询:

SELECT *
FROM book_authors ba
   JOIN books b
     ON b.book_id = ba.book_id
   JOIN book_authors ba2
     ON ba2.book_id = b.book_id
   JOIN authors a
     ON a.author_id = ba2.author_id
WHERE ba.author_id = 1
Run Code Online (Sandbox Code Playgroud)