2015-06-18 97 views
0

考虑用户输入关键字来搜索书籍。首先,应用程序按照书籍标题匹配进行搜索,如果超过50本书符合搜索条件,则返回结果;如果不是,则按书籍作者匹配进行搜索。如果一起不超过50本书匹配,则通过书籍描述匹配搜索。优先搜索 - SQL

SQL可以处理这种情况吗?或者我必须用ifs和elseifs写一个存储过程?

[新增]我使用MySQL5.6。但我觉得答案在于ANSI-SQL,所以我没有指定它。非常感谢您的帮助!

+0

您正在使用哪些DBMS? Postgres的?甲骨文? –

+0

我已经提供了一个答案,应该可以在大多数DBMS中进行一些更改。但请提供您的DBMS,因为它会有所帮助。 :-) – Ionic

回答

1

你可以通过子查询使用union all来实现它。

SELECT DISTINCT TOP(50) bookname 
FROM (
    SELECT TOP(50) bookname, 1 as rank 
    FROM yourTable 
    WHERE bookTitle = N'BLA' 
    UNION 
    SELECT TOP(50) bookname, 2 as rank 
    FROM yourTable 
    WHERE bookAuthor = N'BLA' 
    UNION 
    SELECT TOP(50) bookname, 3 as rank 
    FROM yourTable 
    WHERE bookDescription = N'BLA' 
) as data 
ORDER BY rank 

这适用于SQL Server。在MySQL上,您需要使用LIMIT而不是TOP。 您应该指定您在标签中使用的服务器。

EDIT(由其他用户):

这是一个公认的答案,但它有一个问题,因为它可能返回重复。一本符合所有三个条件的书可以返回三次。 union不会消除它们,因为rank在每一行上都不相同。

一种解决方法是删除等级和使用case声明中order by:由作者

order by (case when bookTitle = N'BLA' then 1 
       when bookAuthor = N'BLA' then 2 
      end) 

编辑: 我改变上述使用定义的列名和一个独特的代码,这将保留副本条目。

+0

辉煌!非常感谢! – lonelyloner

+0

如果没有'ORDER BY',那么* no *保证从'UNION'返回的前50行是(如果存在)50行符合'bookTitle'条件的行。 –

+0

是的你的权利,我已经忘记在战斗的热度。 :-刚刚添加它的例子。 – Ionic

3

一种方法是使用单个查询进行所有比较,然后优先考虑结果。 ANSI标准语法会是这样的:

select b.* 
from books b 
where Title . . . or 
     Author . . . or 
     Description . . . 
order by (case when Title . . . then 1 
       when Author . . . then 2 
       when Description . . then 3 
      end) 
fetch first 50 rows only 

当然,最后一句是不是在所有的数据库支持,所以它可能是limittop什么更糟糕。

如果您有一个大表,并且性能是一个问题,还有其他方法可以对查询进行短语处理,具体取决于匹配条件的样子。