假设我有这个数据(注意第三本书中的空author_id
):
Authors
-------------------------
id | name
-------------------------
1 | Susan Collins
2 | Steven Meyer
-------------------------
Books
--------------------------------------
id | author_id | title
--------------------------------------
1 | 1 | Hunger Games
2 | 2 | Twilight
3 | nil | Games of Throne
--------------------------------------
我有一个图书搜索栏。我想通过书名和作者的名字来搜索它。
例如,当我搜索"苏珊"时。它将归还标题类似"苏珊"或以"苏珊"的名字创作的书籍。
问题是:当我搜索"游戏"时,它只返回"饥饿游戏"。它没有选择"权力的游戏",因为author_id
为空。
我在这里制作了SQLFiddle。
这是从我的Rails代码生成的SQL:
SELECT books.* FROM books
INNER JOIN authors ON authors.id = books.author_id
WHERE (
( LOWER(books.title) LIKE LOWER("%game%") )
OR
( LOWER(authors.name) LIKE LOWER("%game%") )
)
结果只返回1行:"饥饿游戏"。没有《权力的游戏》。
有没有办法包括外键为空的行?
我将接受SQL查询作为答案,我将尝试自己计算Rails代码。
感谢
[编辑]
以下是生成SQL的Rails代码:(我使用Squeelgem)
search = "%#{params[:search]}%" # the query is taken from param
Books.joins(:author).where {
( lower(title) =~ lower(search) ) |
( lower(author.name) =~ lower(search) )
}
您想要的是LEFT JOIN
而不是INNER JOIN
:http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
将Sql Fiddle中的left替换为inner,您将获得有作者和无作者的书籍。
在轨道中,可以通过将joins
替换为includes
来进行左联接。因为它保留了第一个表中没有关系的数据,所以当您想要急于加载关系以防止N+1查询问题时,经常使用它。
也许这就是你想要的。。。
SELECT b.*
FROM books b
LEFT
JOIN authors a
ON a.id = b.author_id
AND a.name LIKE '%game%'
WHERE b.title LIKE '%game%';