2011-02-17 48 views
8

我想要搜索特定字段或者STARTS WITH某个字符串(比方说“ar”)或该字段包含字符串“ar”的记录。SQL语句的WHERE子句中的加权条件

但是,我认为这两个条件不同,因为我限制返回到10的结果数量,我希望STARTS WITH条件比CONTAINS条件的权重更重。

例子:

SELECT * 
FROM Employees 
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%' 
LIMIT 10 

美中不足的是,是,是否有与“AR”,就应该受到青睐开头的名称。我应该找回一个只包含“ar”的名称的唯一方法是,如果有少于10个名称的开头为“ar”

如何对MySQL数据库执行此操作?

回答

10

您需要在两部分中选择它们,并向结果中添加首选标记。 10从每个分段,然后将它们合并并再次把最好10.如果段1产生8个条目,那么段2 UNION的剩下的2

SELECT * 
FROM 
(
SELECT *, 1 as Preferred 
FROM Employees 
WHERE Name LIKE 'ar%' 
LIMIT 10 
UNION ALL 
SELECT * 
FROM 
(
    SELECT *, 2 
    FROM Employees 
    WHERE Name NOT LIKE 'ar%' AND Name LIKE '%ar%' 
    LIMIT 10 
) X 
) Y 
ORDER BY Preferred 
LIMIT 10 
+0

+1。同意,这是更有效的。 – mellamokb

+0

这似乎适用于我。你能解释一下吗?我理解(一般来说)联盟的含义。什么是X和Y以及什么是1和2? –

+1

@Stephen - X和Y只是给子查询的别名(每个派生表必须是别名 - 以便可以在需要时引用它们)。您可以添加一列到任何结果集,只需给出一个值并命名(别名)该列即可。在这种情况下,我在第一部分中添加了一个名为“Preferred”的列,其值为1,第二部分中的值为2。列现在是结果的一部分(用于查询)。 – RichardTheKiwi

4

分配码值的结果,排序码值:

select 
    *, 
    (case when name like 'ar%' then 1 else 2 end) as priority 
from 
    employees 
where 
    name like 'ar%' or name like '%ar%' 
order by 
    priority 
limit 10 

编辑:

见理查德又名cyberkiwi的回答更高效的解决方案,如果有潜在的很多比赛。

+0

应受益,那么这可能会比较慢,因为它必须首先为所有匹配分配一个优先级。 – RichardTheKiwi

0

试试这个(没有MySQL实例立即可用来测试):

SELECT * FROM 
    (SELECT * FROM Employees WHERE Name LIKE 'ar%' 
    UNION 
    SELECT * FROM Employees WHERE Name LIKE '%ar%' 
    ) 
LIMIT 10 

可能有更好的方法来做到这一点,但立即窜出来的想法。

0

我的解决方案都将产品是:

SELECT * 
FROM Employees 
WHERE Name LIKE '%ar%' 
ORDER BY instr(name, 'ar'), name 
LIMIT 10 

instr()寻找所述模式的第一次出现。 AR%将在xxAR之前出现。

这可以防止:

  1. 应该只能做表扫描1次。联合和派生表做3. 3.列上的前两个过滤出模式,然后是子集中的第三个,以找到它们相等的位置 - 因为联合会过滤掉模糊。

  2. 根据模式的位置给出一个真正的排序。 WX> xW,它们> XXW>等...

0
SELECT * 
FROM Employees 
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%' 
ORDER BY LIKE 'ar%' DESC 
LIMIT 10 

应该由工单二进制真/假像,如果index'ed如果表中包含许多比赛从指数