A ideia é criar uma consulta que será usada como preenchimento automático, mas que moverá os resultados que tiverem a palavra-chave exata para o topo.
A primeira parte da consulta p1 busca por correspondência exata enquanto a última parte p2 busca por qualquer ocorrência de uma substring. Isso significa que o provedor que tem " One " em seu nome será selecionado em uma primeira parte e o provedor que tem " Done " em seu nome será selecionado em uma segunda parte.
O problema é que a segunda parte seleciona itens da primeira parte também.
Por causa disso, tentei adicionar um alias para cada parte da união e também tentei adicionar uma condição adicional à última parte da união:AND p2.id != p1.id
Isso não funcionará com o MySQL:
Erro SQL (1054): Coluna desconhecida 'p1.id' na 'cláusula where'.
Também tentei com HAVING
, mas sem sorte.
A questão é: existe uma maneira de obter esse resultado de uma só vez?
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;
Dados de amostra:
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
O resultado esperado:
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
Acho que você pode usar a função instr(...) mais barata e selecionar todas as linhas de uma só vez.
Veja o exemplo
Com dados de teste
violino