SQL 同时使用相等和相似的条件

SQL use equal and like condition together

我需要 assemble 一个 sql 查询,该查询仅在 return 值不等于

时才执行 LIKE

首先使用equal如果没有值使用LIKE

SELECT * 
FROM cars 
WHERE name = 'Ferrari Basic' 
OR name LIKE '%Ferrari Basic%' 
LIMIT 1;

预期:法拉利基本款

Table 例子

id name
1 Ferrari Basic Test
2 Test Ferrari Basic
3 Ferrari Basic
4 Test Ferrari Basic Test

文本搜索引擎通常使用评分系统。评分逻辑的一个非常基本的实现如下所示:

select *
from (
  SELECT *,
    case when name = 'Ferrari Basic' then 2 else 1 end as score
  FROM cars 
  WHERE name LIKE '%Ferrari Basic%'
) x
order by score desc
LIMIT 1;

在这种情况下,与 = 的比赛将获得 2 分,而与 LIKE 的比赛将仅获得 1 分。然后你select得分最高的比赛。

您可以为包含模式 'Ferrari Basic' 的所有行筛选 table,并在 ORDER BY 子句中移动 name 等于 'Ferrari Basic'(如果存在)在顶部仅选择第一行:

SELECT * 
FROM cars 
WHERE name LIKE '%Ferrari Basic%'
ORDER BY name = 'Ferrari Basic' DESC 
LIMIT 1;

参见demo

如果您正在寻找最佳匹配,请按匹配质量对行进行排序。你定义这是什么。在您的示例中,名称长度可能有效(添加到搜索词中的字符越少,匹配越好):

SELECT * 
FROM cars 
WHERE name LIKE '%Ferrari%Basic%' 
ORDER BY CHAR_LENGTH(name)
LIMIT 1;

但是你当然可以有更复杂的表达式,我会使用 CASE WHEN:

SELECT * 
FROM cars 
WHERE name LIKE '%Ferrari%Basic%' 
ORDER BY 
  CASE WHEN name = 'Ferrari Basic' THEN 1 -- exact match
       WHEN name LIKE 'Ferrari Basic%' THEN 2 -- exact match at the beginning
       WHEN name LIKE '%Ferrari Basic' THEN 3 -- exact match at the end
       WHEN name LIKE '%Ferrari Basic%' THEN 4 -- exact match in the middle
       ELSE 5 -- there is something between the two search words
  END
LIMIT 1;

或者,如果您只想要完全匹配(如果可用)而所有 non-exact 都匹配,请使用 DENSE_RANK(因为 MySQL 的 LIMIT 子句没有选项包括领带):

SELECT *
FROM
(
  SELECT 
    cars.*,
    DENSE_RANK() OVER (ORDER BY name = 'Ferrari Basic' DESC) AS rnk
  FROM cars 
  WHERE name LIKE '%Ferrari%Basic%' 
  ORDER BY 
) ranked
WHERE rnk = 1;

(这利用了 MySQL 的 true = 1,false = 0。如果您更喜欢,当然可以使用 CASE 表达式。)