这个想法是创建一个查询,该查询将用作自动完成功能,但会将具有确切关键字的结果移至顶部。
查询的第一部分 p1 搜索完全匹配,而最后一部分 p2 搜索子字符串的任何出现。这意味着名称中包含“One”的提供商将在第一部分中选择,而名称中包含“Done”的提供商将在第二部分中选择。
问题是第二部分也从第一部分中选择项目。
因此,我尝试为联合的每个部分添加别名,并尝试为联合的最后部分添加附加条件:
AND p2.id != p1.id
这不适用于 MySQL:
SQL 错误 (1054):“where 子句”中存在未知列“p1.id”。
也尝试过
HAVING
,但一点运气都没有。
SELECT * FROM (
(SELECT DISTINCT
p1.*,
1 AS priority,
CASE WHEN parent_id IS NULL THEN 1 ELSE 2 END AS is_parent
FROM provider p1
WHERE CONCAT(' ', name, ' ') LIKE '% one %'
LIMIT 100)
UNION
(SELECT DISTINCT
p2.*,
2 AS priority,
CASE WHEN parent_id IS NULL THEN 1 ELSE 2 END AS is_parent
FROM provider p2
WHERE name LIKE '%one%' AND p2.id != p1.id
LIMIT 100)
ORDER BY priority, is_parent
) AS t LIMIT 100;
样本数据:
ID | Parent ID | Name
---------------------------
1 | <NULL> | One dove
2 | 1 | One play
3 | <NULL> | Monitor
4 | 1 | Day one
5 | <NULL> | Drone
6 | <NULL> | Screen
7 | <NULL> | Done with you
8 | <NULL> | Not done
9 | <NULL> | All as one
结果如下:
ID | Parent ID | Name | Priority | Is parent
------------------------------------------------------
1 | <NULL> | One dove | 1 | 1
9 | <NULL> | All as one | 1 | 1
2 | 1 | One play | 1 | 2
4 | 1 | Day one | 1 | 2
5 | <NULL> | Drone | 2 | 1
7 | <NULL> | Done with you | 2 | 1
8 | <NULL> | Not done | 2 | 1
我认为您可以使用更便宜的 instr(...) 函数并一次性选择所有行。
参见示例
select *
from(
select *
,case when instr(Name,' one ')>0 then 1
when instr(Name,'one ')=1 then 1
when instr(Name,' one')>0 then 1
when instr(Name,'one')>0 then 2
else 0
end priority
from test t
)a
where priority>0
身份证 | 家长_ID | 姓名 | 优先 |
---|---|---|---|
1 | 空 | 一只鸽子 | 1 |
2 | 1 | 一场比赛 | 1 |
4 | 1 | 第一天 | 1 |
5 | 空 | 无人机 | 2 |
7 | 空 | 跟你完事了 | 2 |
8 | 空 | 未完成 | 2 |
9 | 空 | 众生皆为一 | 1 |
有测试数据
身份证 | 家长_ID | 姓名 |
---|---|---|
1 | 空 | 一只鸽子 |
2 | 1 | 一场比赛 |
3 | 空 | 监控 |
4 | 1 | 第一天 |
5 | 空 | 无人机 |
6 | 空 | 屏幕 |
7 | 空 | 跟你完事了 |
8 | 空 | 未完成 |
9 | 空 | 众生皆为一 |