Inner Join/Join On不符合预期,购书推荐SQL查询问题求助
解决基于元关键字的图书推荐SQL问题
我来帮你搞定这个图书推荐的SQL难题!先理清楚你的核心需求:你想给已购买书籍13和14(不过你提到查询SELECT c.book FROM customers_books c WHERE c.customer = 1返回13、11,这里可能是笔误?先按你最终要推荐书籍3的目标来)的客户,找出唯一和这两本书都共享元关键字的图书。
你提到的AND bmk2.book <> bmk1.book没按预期工作,问题出在这个条件只能排除当前关联的两本书相同,但没法排除客户已经购买的其他书籍,也没法确保推荐的图书和所有已购书籍都有匹配的关键字。
正确的SQL实现方案
我给你写一个逻辑清晰的查询,完美匹配你的需求:
-- 第一步:先获取客户已购买的书籍列表,用CTE让逻辑更清晰 WITH customer_purchased AS ( SELECT book FROM customers_books WHERE customer = 1 ) -- 第二步:关联元关键字表,找到所有和已购书籍共享关键字的非已购图书 SELECT bmk2.book AS recommended_book FROM book_meta_keywords bmk1 -- 关联已购书籍的关键字记录 JOIN customer_purchased cp ON bmk1.book = cp.book -- 关联有相同关键字的其他图书记录 JOIN book_meta_keywords bmk2 ON bmk1.meta_keyword = bmk2.meta_keyword -- 排除客户已经买过的书籍 WHERE bmk2.book NOT IN (SELECT book FROM customer_purchased) -- 确保推荐的图书和所有已购书籍都有匹配的关键字(这一步是筛选核心) GROUP BY bmk2.book HAVING COUNT(DISTINCT bmk1.book) = (SELECT COUNT(*) FROM customer_purchased);
关键逻辑拆解
- CTE
customer_purchased:把客户已购书籍单独提取出来,后续多次调用时更简洁,也方便后续调整查询条件。 - 双重关联元关键字表:
bmk1对应已购书籍的关键字记录,bmk2对应有相同关键字的其他图书记录,这样能快速定位所有相关候选图书。 NOT IN排除已购书籍:这比你原来的bmk2.book <> bmk1.book靠谱得多——后者只能排除bmk1对应的那一本,但如果bmk2是客户已购的另一本书(比如11),这个条件就拦不住,而NOT IN直接排除所有已购书籍。GROUP BY+HAVING确保全匹配:COUNT(DISTINCT bmk1.book)统计候选图书匹配的已购书籍数量,和已购书籍总数相等,就说明它和每一本已购书都有共享关键字,正好筛选出你要的书籍3(如果只需要和至少一本已购书匹配,去掉这两行即可)。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

