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
表达式。)
我需要 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
表达式。)