Mysql 无法确定WHERE子句应该是什么

Mysql 无法确定WHERE子句应该是什么,mysql,sql,database,join,Mysql,Sql,Database,Join,我一直在创建MySQL查询。下面是我的数据库结构 作者(作者id和作者姓名) 图书(图书id和书名) books\u authors是链接表(book\u id和author\u id) 所有书籍和作者的结果: 我需要获得特定作者的所有书籍,但如果一本书有两位作者,则必须同时显示第二位作者。例如,book_id=2的《吉兆》一书有两位作者。当我运行查询时,我得到了作者的书籍_id=1,但我不能在结果中包括第二位作者——“Neil Gaiman”。查询是: SELECT * FROM books

我一直在创建MySQL查询。下面是我的数据库结构

作者
(作者id和作者姓名)

图书
(图书id和书名)

books\u authors
是链接表(book\u id和author\u id)

所有书籍和作者的结果:

我需要获得特定作者的所有书籍,但如果一本书有两位作者,则必须同时显示第二位作者。例如,book_id=2的《吉兆》一书有两位作者。当我运行查询时,我得到了作者的书籍_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
结果如下:


您需要更改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)
查询的问题在于WHERE子句不仅过滤结果集中得到的书籍,还过滤书籍作者关联

在这个子查询中,您首先使用作者id来过滤书籍,然后使用这些书籍id来获取所有关联的作者


另一方面,我认为在这种特殊情况下,用内部连接代替外部连接的建议应该适用。books_authors上的第一个左外部联接肯定是无用的,因为WHERE子句保证每个选定的book_id在该表中至少存在一行。第二个左外部联接可能是无用的,因为我希望author_id是authors表的主键,我希望books_authors表有一个外键,并且author_id上有一个NOTNULL约束。。。这意味着您不应该有一个不引用特定作者行的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)
请注意,在大多数情况下,内部联接可能比外部联接更有效(它们为引擎提供了更多关于如何执行stament和获取结果的选择)。因此,如果没有严格必要,您应该避免外部连接


我添加了别名并从结果集中删除了多余的列。

您很接近。。。基本上,您需要识别author_id=?。然后再次将其与book_author表连接,以使所有作者都与这些图书ID关联。然后加入图书和作者,以获得您的图书和作者姓名

希望下面的内容在这方面是非常清楚的,但如果不是让我知道,我会帮助解释更多细节

SELECT a.*, d.* FROM books as a
   INNER JOIN (SELECT book_id FROM books_authors WHERE author_id=?) as b
       ON a.book_id=b.book_id 
   INNER JOIN books_authors  as c
       ON b.book_id=c.book_id
   INNER JOIN authors AS d
       ON d.author_id  = c.author_id 
顺便说一句,你也可以用WHERE EXISTS子句来构造它。我认为无论哪种方式,您都不会看到太大的性能差异,但仅供参考,如果需要,您可以尝试一下。使用EXPLAIN查看查询的执行计划。如果有问题的话,还有其他方法可以剥这只猫的皮


另外,确保你注意指数。无论您使用这里的方法,还是Frazz描述的方法,复合/多列/复杂索引都可能对您产生很大的影响。也就是说,考虑使用BooGyID和AuthopyID、BoojyID来索引书本作者。是否应使用附加联接、IN或EXISTS子查询。。。给猫剥皮的方法很多。不管怎样,对图书作者建立多栏索引可能会对您有所帮助,尤其是如果此表很大,您不需要对此进行子查询:

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

使用子查询生成图书ID列表,然后列出与这些图书ID关联的所有作者/这就是我所说的——几乎!:-)对当你的评论出现时,我已经在回答了。。。很抱歉,别担心我的评论有缺陷-你的答案更正确-添加别名,因为它现在模棱两可(books_id在books和books_authors中),MySQL不会喜欢它。“顺便说一句,我确实认为在这种特定情况下,用内部联接替换外部联接的建议应该适用。”我也在想同样的事情,我非常同意Frazz在这一点上的观点,嗯…这似乎并没有给出预期的结果。抢手货问题是左连接。我在想说,你知道,不确定加入一个好主意。如果需要左连接,请使用子查询方法。如果您不这样做,请使用任何更快或更容易维护的工具(如果他们的表现相同)