这个想法是创建一个查询,它将用作自动完成,但它会将具有精确关键字的结果移动到顶部。
查询的第一部分 p1 搜索精确匹配,而最后一部分 p2 搜索任何子字符串的出现。这意味着在第一部分中将选择名称中包含“ One ”的提供商,而在第二部分中将选择名称中包含“ Done ”的提供商。
问题是第二部分也从第一部分中选择了项目。
因此,我尝试为 union 的每个部分添加别名,并尝试为 union 的最后一部分添加附加条件: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(...) 函数并一次性选择所有行。
查看示例
有测试数据
小提琴