What you are asking for is the "anti join" fragrance. There are several ways to achieve it; here is one:
SELECT b.* FROM books_table b LEFT JOIN keywords_table k ON b.book_id = k.book_id AND k.keyword_id IN (1,2,3) WHERE k.book_id IS NULL AND b.is_hardcover = 1
The left join matches each row from the left table ( books_table ) with those rows in the right table that satisfy the condition b.book_id = k.book_id AND k.keyword_id IN (1,2,3) , and includes a single result row for each row left table, t matches any row of the right table. The filter condition k.book_id IS NULL conflicts with the join condition, so it can be satisfied only by those lines that arise from the left line that does not correspond to any right line.
Note that assigning conditions to a join predicate and a filter predicate is critical with an outer join such as this. Also note that in this case there is no need for a GROUP BY if books_table cannot contain a duplicate book_id s.
This approach is likely to be better in practice than based on the correlated subquery in the WHERE . However, if performance is important, then it will be useful for you to check out the alternatives that you are considering.
source share