2011-02-17 49 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如果表中包含許多比賽從指數