SQL LIKE,如何按加权发生次数对结果进行排序?

时间:2011-02-24 11:35:03

标签: sql sql-order-by search-engine

我有我的搜索词:

"Yellow large widgets"

我将这些术语分为3个单词:

1 = "Yellow";
2 = "Large";
2 = "Widgets";

然后我搜索:

SELECT * FROM widgets
    WHERE (description LIKE '%yellow%' OR description LIKE '%large%' OR description LIKE 'widgets') 
    OR (title LIKE '%yellow%' OR title LIKE '%large%' OR title LIKE '%widgets%')

如何根据这些偏差对结果进行排序?

  • 标题需要总统,如果标题中出现任何条款,则应将其视为更重要
  • 发生次数,总出现率较高的结果应首先出现

理想方法

  • description
  • 中计算出现次数
  • 此处每次出现都值1 point
  • title
  • 中计算出现次数
  • 每次title次出现都值5 points
  • 按点排序。

但我不知道在SQL中从哪里开始这样做。

4 个答案:

答案 0 :(得分:10)

好的,让我们将您的搜索字词放在临时表中:

CREATE TABLE #SearchTerms (Term varchar(50) not null)
insert into #SearchTerms (Term)
select 'yellow' union all
select 'large' union all
select 'widgets'

让我们做一些愚蠢的事情:

select
    widgets.ID,
    (LEN(description) - LEN(REPLACE(description,Term,''))) / LEN(Term) as DescScore
    (LEN(title) - LEN(REPLACE(title,Term,''))) / LEN(Term) as TitleScore
from
    widgets,#SearchTerms

我们现在已经在描述和标题中计算了每个术语的每次出现次数。

所以现在我们可以对这些事件求和并加权:

select
    widgets.ID,
    SUM((LEN(description) - LEN(REPLACE(description,Term,''))) / LEN(Term) +
    ((LEN(title) - LEN(REPLACE(title,Term,''))) / LEN(Term) *5)) as CombinedScore
from
    widgets,#SearchTerms
group by
    Widgets.ID

如果我们需要做更多的事情,我建议将上面的内容放在子选择

select
    w.*,CombinedScore
from
    widgets.w
       inner join
    (select
        widgets.ID,
        SUM((LEN(description) - LEN(REPLACE(description,Term,''))) / LEN(Term) +
        ((LEN(title) - LEN(REPLACE(title,Term,''))) / LEN(Term) *5)) as CombinedScore
    from
        widgets,#SearchTerms
    group by
        Widgets.ID
    ) t
        on
            w.ID = t.ID
where
    CombinedScore > 0
order by
    CombinedScore desc

(请注意,我假设所有这些示例中都有一个ID列,但可以将其扩展为在窗口小部件表中定义PK所需的列数)


这里真正的技巧是计算更大的文本体中单词的出现次数,这可以通过以下方式计算:

(LEN(text) - LEN(text with each occurrence of term removed)) / LEN(term)

答案 1 :(得分:3)

选择以下选项之一:

  • 使用全文搜索引擎(Lucene或类似代码)进行加权全文搜索;
  • 请参阅this other StackOverflow question
  • 执行多个SELECT,每个{em>相关字段,将它们与UNION合并,然后对结果进行排序;
  • 在检索结果后,在您的应用程序中对结果进行排序。

答案 2 :(得分:0)

快速入侵(对于mysql,你可以在其他dbs上使用类似的结构)。注意,未经测试。

SELECT description, title
  FROM
(SELECT description, title,
        IF(description LIKE '%yellow%' OR 
           description LIKE '%large%' OR 
           description LIKE 'widgets' 2, 0) +
        IF(title LIKE '%yellow%' OR 
           title LIKE '%large%' OR
           title LIKE '%widgets%', 1, 0) AS w
  FROM widget)
 WHERE w > 0
ORDER BY w

答案 3 :(得分:0)

也许这样

   SELECT description, title ,
            (       IF(title LIKE '%yellow%', 2, 0) +
            IF(title LIKE '%large%', 2, 0) +
            IF(title LIKE '%widgets%', 2, 0)+       IF(description LIKE '%yellow%', 1, 0) +
            IF(description LIKE '%large%', 1, 0) +
            IF(description LIKE '%widgets%', 1, 0)      )   AS w 

    FROM widget ORDER BY w DESC