Count和Order By Where子句匹配

时间:2011-12-16 11:18:57

标签: sql postgresql entityspaces

我正在为FAQ的列表编写一些非常简单的搜索功能。我正在将搜索字符串拆分为各种字符,包括空格。然后按照

的顺序执行选择
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匹配的数量并按顺序排序,以便将具有最多关键字的问题显示在结果的顶部?

2 个答案:

答案 0 :(得分: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 Insertion attacks的风险?

答案 1 :(得分: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".