【问题标题】:Mysql join to find "missing" "related" rowsMysql 加入以查找“丢失”“相关”行
【发布时间】:2012-03-13 22:46:24
【问题描述】:

我在两个表之间有所有权关系, 说users(int user_id)user_books(int user_book_id,int user_id,int book_id) 以及另外两个表books(int book_id, varchar book_title, int author_id)authors (int author_id, varchar author_name)

给定一个特定的user_id,我想获取用户没有的书,作者所写的书,他确实有他们写的其他书。

因此,如果用户有 BOOK1(即在user_books 中有一行)并且没有由与 BOOK1 相同的作者编写的 BOOK2 和 BOOK3,我想获取 BOOK2 和 BOOK3 的 ID。

我想我可以使用 SELECT WHERE NOT IN () 来做到这一点,但出于性能原因,我正在寻找基于连接的解决方案。

【问题讨论】:

  • 你试过使用外连接吗?
  • 正如我所说,我可以使用“select where not in”来写这个,但我想使用连接。我知道应该使用左连接以某种方式完成,但我不确定具体如何。
  • 我也有一个问题,即某些用户可能已经拥有不止一个 user_book,因此加入会多次返回作者 ID。
  • 我应该从查找“相关”作者的所有书籍开始吗?

标签: mysql left-join


【解决方案1】:

我会检查性能与“不在”或其他解决方案,但我相信以下方法会起作用:

select exist.userId, b.bookTitle, a.authorName  
from (select distinct ub.userId, b.authorId  
         from userBooks ub  
           inner join books b on b.bookId = ub.bookId  
         where ub.userId = @userId) exist  
  inner join Authors a on a.authorId = exist.authorId  
  inner join Books b on b.authorId = a.authorId  
  left outer join userBooks ub on ub.bookId = b.bookId and ub.userId = exist.userId  
where ub.userId is null

派生表查找用户喜欢的所有作者,然后查询的其余部分查找相同作者的其他书籍

【讨论】:

  • 你是对的 - 这行得通,但它比使用 IN 和 NOT IN 复杂得多(如你所料)。如果您对查询进行解释,您会看到有 4 个 PRIMARY 查询和 2 个 DERIVED 查询(一个使用临时表)。而“选择 * from books where author_id in (select author_id from user_books as ub join books as b on b.book_id = ub.book_id) and book_id not in (select book_id from user_books where user_id = @uid);”有四个查询,都使用 where(因此有资格使用索引进行加速)。我同意衡量这两种方法对于选择最佳方法是必要的。
  • @D Mac - 完全正确。你不能采取批发“不要使用NOT IN”的方法。仅仅因为没有它们就可以做到这一点并不意味着您应该……正如您建议的那样,查看查询的处理方式要好得多。我只是想证明可能,但我会根据分析推荐
  • 谢谢你们,我会尝试从这里解决问题。 @D Mac 据我所知,在您提供的语法中,第一个子查询中缺少 where user_id = @uid。甚至强硬的我的书籍表在 author_id 和 book_id 上都有一个索引,两者都没有使用。
  • @KAJ 特定用户 id 在哪里输入这个查询?
  • 在派生表位中 - 根据更新的答案。请注意@D Mac 和我自己的性能cmets
猜你喜欢
  • 2021-01-17
  • 2013-08-31
  • 2014-12-07
  • 2011-07-28
  • 2011-02-19
  • 1970-01-01
  • 2019-12-16
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多