SQL文本搜索和订购

时间:2008-09-17 02:39:33

标签: sql search

我有一个问题:

SELECT *
FROM Items
WHERE column LIKE '%foo%'
   OR column LIKE '%bar%'

如何订购结果?

假设我的行与'foo'匹配,行与'bar'匹配,但我也有一行'foobar'。

如何订购返回的行,以便第一个结果是匹配更多LIKE的结果?

10 个答案:

答案 0 :(得分:4)

RDBMS支持的案例或条件构造是一种方法

select *, case when col like '%foo%' and col like '%bar%' then 2 end 
else 1 end as ordcol 
from items 
where col like '%foo%' or col like '%bar%' order by ordcol

答案 1 :(得分:2)

SELECT * FROM Items WHERE column LIKE '%foo%' OR column LIKE '%bar%' 
ORDER BY 
(IF(column LIKE '%foo%',1,0) + IF(column LIKE '%bar%',1,0)) 
DESC

if的语法是

IF ( condition, true_value, false_value )

答案 2 :(得分:1)

您可以使用UNION

SELECT * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%'
UNION
SELECT * FROM Items WHERE column LIKE '%foo%' AND NOT (column LIKE '%bar%')
UNION
SELECT * FROM Items WHERE column LIKE '%bar%' AND NOT (column LIKE '%foo%');

但这可能是糟糕的表现。更糟糕的是,我猜你想用它来构建一个首先给出最有意义的结果的搜索引擎,然后单词的数量不会限制为2。

在这种情况下,您可以创建一个包含匹配数的score列。像这样:

SELECT
    *,
    (IF(column LIKE '%bar%', 1, 0) + IF(column LIKE '%foo%', 1, 0)) AS score
FROM Items
WHERE column LIKE '%foo%' OR column LIKE '%bar%'
ORDER BY score DESC;

我的SQL有点生疏,但至少在MySQL 5.0中应该是这样的。另请参阅IF函数的手册: http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html

答案 3 :(得分:1)

SELECT * FROM Items
WHERE col LIKE '%foo%'
    OR col LIKE '%bar%'
ORDER BY CASE WHEN col LIKE '%foo%' THEN 1
                WHEN col LIKE '%bar%' THEN 2
            END

答案 4 :(得分:0)

哪个DBMS?

例如,它可以通过CTE或Union完成,但如果您使用的是MySQL,那么您可以忘记它。

答案 5 :(得分:0)

试试这段代码:

SELECT * FROM Items WHERE column LIKE '%foo%' OR column LIKE '%bar%'
order by (select count(*) from items i where i.column= item.column) DESC 

如果您不关心细节,也可以按columncount(*)然后ORDER进行分组。

答案 6 :(得分:0)

你可能想要这样做:

SELECT *
FROM Items
WHERE column LIKE '%foo%' OR column LIKE '%bar%'
ORDER BY CASE WHEN column LIKE '%foo%' AND column LIKE '%bar%' THEN 1 ELSE 0 END DESC

注意:这是干编码的,可能不太便携。

答案 7 :(得分:0)

2个查询:

SELECT * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%';
SELECT * FROM Items WHERE (column LIKE '%foo%' AND column NOT LIKE '%bar%') OR (column NOT LIKE '%foo%' AND LIKE '%bar%')

(SQL中没有XOR)

答案 8 :(得分:0)

并非所有RDBMS都支持IF(或Oracle中的DECODE)语句。如果不是,您可以使用子查询来定义表“a”并搜索所有员工的名为JO SMITH或组合。

SELECT 
 a.employee_id,
 a.surname,
 sum(a.counter)
FROM

 (SELECT
   employee_id,
   surname,
   1 as counter
  FROM
   MyTable
  WHERE
   surname like '%SMITH%'

  UNION ALL

  SELECT
   employee_id,
   surname,
   1 as counter
  FROM
   MyTable
  WHERE
   surname like '%JO%'
   ) a

GROUP BY 
 a.employee_id,
 a.surname
ORDER BY 3,1,2

确保使用UNION ALL,否则无效。您也可以使用UPPER()来使您的搜索不区分大小写。

答案 9 :(得分:0)

当您的查询当前已写入时,WHERE子句不会为您提供可用于对结果进行排序的任何信息。我喜欢Brian's idea;添加一个常量列和UNION查询,你甚至可以在一个结果集中获取所有内容。例如:

SELECT 1 as rank, * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%'
UNION
SELECT 2 as rank, * FROM Items WHERE column LIKE '%foo%' AND column NOT LIKE '%bar%'
UNION
SELECT 2 as rank, * FROM Items WHERE column LIKE '%bar%' AND column NOT LIKE '%foo%'
ORDER BY rank

然而,这只会给你这样的东西:

  • 与foo和匹配栏匹配的所有行的无序集合
  • 后跟(无序集合)所有匹配foo或bar的行,但不是两者(尽管您可以在最后一个SELECT语句中使用不同的常量将其分解为两个单独的组)。

这可能正是您正在寻找的内容,但它不会告诉您哪些行与foo匹配三次,或者在仅包含一个foo实例的行之前对它们进行排序。所有那些喜欢的东西也会变得昂贵。如果您真正想要做的是根据相关性对结果进行排序(无论您如何定义),最好使用全文索引。如果你正在使用MS SQL Server,它有一个内置服务可以做到这一点,还有第三方产品也会这样做。

编辑:看完所有其他答案后(当我开始我的时候只有两个 - 我显然需要学会更快思考;-))很明显有有几种方法可以解决这个问题,具体取决于你想要完成的工作。我建议您根据他们在您的系统上执行的方式来测试和比较解决方案。我不是一个性能/调优专家,但是函数往往会减慢速度,特别是如果你对函数的结果进行排序的话。 LIKE运算符也不一定是spry。作为开发人员,使用熟悉的结构(如“IF”和“CASE”)似乎很自然,但使用更多基于集合的方法的查询通常在RDMS中具有更好的性能。再次,YMMV,所以最好测试你是否完全关心性能。