2011-12-16 57 views
2

我正在为FAQ列表编写一些非常简单的搜索功能。我将搜索字符串分割为各种字符,包括空格。然后进行选择沿计数和顺序通过Where子句匹配

SELECT * 
FROM "faq" 
WHERE 
    ((LOWER("Question") LIKE '%what%' 
    OR LOWER("Question") LIKE '%is%' 
    OR LOWER("Question") LIKE '%a%' 
    OR LOWER("Question") LIKE '%duck%')) 

我有过的线稍微修改成我们的数据访问层的产生,但它应该给你什么事的想法。

上述查询很好地证明了这个问题,因为大多数问题都可能包含单词a或其中的单词,但是我无法将其过滤出来,因为首字母缩写词对于搜索者来说可能很重要。建议的是我们按匹配关键字的数量排序。然而,我一直无法找到一种在SQL中这样做的方法(我们没有时间创建一个带有关键字索引的简单搜索引擎等)。有谁知道是否有一种方法可以计算SQL语句中LIKE匹配的数量并按此顺序进行排序,以便最多关键字的问题出现在结果的顶部?

回答

3

我想匹配的关键字列表正在进入由用户并且在执行查询之前立即由应用程序动态地插入到查询中。如果是的话,我建议修改查询,像这样:

SELECT * 
FROM "faq" 
WHERE 
    ((LOWER("Question") LIKE '%what%' 
    OR LOWER("Question") LIKE '%is%' 
    OR LOWER("Question") LIKE '%a%' 
    OR LOWER("Question") LIKE '%duck%')) 
order by 
    case when LOWER("Question") LIKE '%what%' then 1 else 0 end + 
    case when LOWER("Question") LIKE '%is%' then 1 else 0 end + 
    case when LOWER("Question") LIKE '%a%' then 1 else 0 end + 
    case when LOWER("Question") LIKE '%duck%' then 1 else 0 end 
descending; 

这甚至让你“重量”每个选择项的重要性,假设用户(或算法)可以分配的权重,以每学期。

一个警告:如果您的查询是动态构建的,您是否意识到SQL Insertionattacks的风险?

+0

感谢PgAdmin似乎完美的工作。我们使用称为Entityspaces的数据访问层来为我们清理数据。但是,我们可能必须自己构建此查询,因此将谨慎行事:) – ClearCarbon 2011-12-16 13:37:06

2

你可以写一个计算一个字符串的出现在另一个这样的功能:

CREATE OR REPLACE FUNCTION CountInString(text,text) 
RETURNS integer AS $$ 
SELECT(Length($1) - Length(REPLACE($1, $2, '')))/Length($2) ; 
$$ LANGUAGE SQL IMMUTABLE; 

而在选择使用它:select CountInString("Question",' what ') from "faq".

+0

我相当肯定这种方法的效果不错,不过按顺序排列的方案更适合我们目前的情况。 – ClearCarbon 2011-12-16 15:03:02