Взвешенные условия в предложении WHERE оператора SQL

Я хочу искать записи, в которых конкретное поле НАЧИНАЕТСЯ С некоторой строкой (скажем, «ar») ИЛИ это поле СОДЕРЖИТ строку «ar».

Тем не менее, я считаю эти два условия разными, потому что я ограничиваю количество возвращаемых результатов до 10 и хочу, чтобы условие STARTS WITH имело больший вес, чем условие CONTAINS.

Пример:

SELECT *
FROM Employees
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%'
LIMIT 10

Загвоздка в том, что если есть имена, НАЧИНАЮЩИЕСЯ с «ar», им следует отдавать предпочтение. Единственный способ вернуть имя, которое просто СОДЕРЖИТ «ar», - это если есть МЕНЬШЕ 10 имен, НАЧИНАЮЩИХСЯ с «ar».

Как я могу сделать это с базой данных MySQL?


person Stephen Stchur    schedule 17.02.2011    source источник


Ответы (5)


Вам нужно выбрать их в 2 частях и добавить к результатам тег Preference. 10 из каждого сегмента, затем объедините их и снова возьмите лучшие 10. Если сегмент 1 дает 8 записей, то сегмент 2 UNION ALL произведет оставшиеся 2

SELECT *
FROM
(
SELECT *, 1 as Preferred
FROM Employees
WHERE Name LIKE 'ar%'
LIMIT 10
UNION ALL
SELECT *
FROM
(
    SELECT *, 2
    FROM Employees
    WHERE Name NOT LIKE 'ar%' AND Name LIKE '%ar%'
    LIMIT 10
) X
) Y
ORDER BY Preferred
LIMIT 10
person RichardTheKiwi    schedule 18.02.2011
comment
Кажется, это работает для меня. Вы вообще можете это объяснить? Я понимаю (вообще говоря), что означает союз. Что такое X и Y и что такое ,1 и ,2? - person Stephen Stchur; 18.02.2011
comment
@Stephen - X и Y - это просто псевдонимы, данные подзапросам (каждая производная таблица должна иметь псевдоним, чтобы на них можно было ссылаться при необходимости). Вы можете добавить столбец в любой результирующий набор, просто указав значение и назвав (псевдоним) столбец. В этом случае я добавил столбец Preferred со значением 1 в первой части и значением 2 во второй части. Столбцы теперь являются частью результата (для запроса). - person RichardTheKiwi; 18.02.2011
comment
Большой! Это сработало для меня. А что, если мне нужен случайный порядок в подзапросах. Другими словами, отсортированы по группам 1 и 2, но в случайном порядке внутри каждой группы. Я попытался добавить ORDER BY RAND() к каждому из подзапросов и получил ошибку: Общая ошибка: 1221 Неправильное использование UNION и ORDER BY' Можно ли их вообще не использовать вместе? - person Joshua Goossen; 02.05.2015
comment
@JoshuaGoossen используйте ORDER BY Preferred, Rand() в самом конце - person RichardTheKiwi; 06.05.2015

Присвойте результатам кодовое значение и отсортируйте по кодовому значению:

select
    *,
    (case when name like 'ar%' then 1 else 2 end) as priority
from
    employees
where
    name like 'ar%' or name like '%ar%'
order by
    priority
limit 10

Изменить:

См. Ответ Ричарда, также известного как Cyberkiwi, для более эффективного решения, если совпадений может быть много.

person mellamokb    schedule 17.02.2011
comment
Если таблица содержит много совпадений, это может быть медленнее, так как сначала необходимо назначить приоритет всем совпадениям. - person RichardTheKiwi; 18.02.2011

Мое решение:

SELECT *
FROM Employees
WHERE Name LIKE '%ar%'
ORDER BY instr(name, 'ar'), name
LIMIT 10

instr() ищет первое вхождение рассматриваемого шаблона. AR% будет стоять перед xxAR.

Это предотвращает:

  1. Следует выполнять сканирование таблицы только 1 раз. Объединения и производные таблицы делают 3. Первые два в столбцах для фильтрации шаблонов, а затем 3-й в подмножестве, чтобы найти, где они равны, поскольку объединение отфильтровывает дубликаты.

  2. Дает истинную сортировку на основе расположения шаблона. Wx > xW > xxW > и т.д...

person petemill66    schedule 18.02.2011
comment
Это действительно убийственное решение! Лаконично и эффективно! - person Niket Pathak; 09.09.2018

Попробуйте это (у вас нет экземпляра MySQL, доступного для тестирования):

SELECT * FROM
   (SELECT * FROM Employees WHERE Name LIKE 'ar%'
    UNION
    SELECT * FROM Employees WHERE Name LIKE '%ar%'
   )
 LIMIT 10

Вероятно, есть лучшие способы сделать это, но это сразу пришло в голову.

person Derek Prior    schedule 17.02.2011

SELECT *
FROM Employees
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%'
ORDER BY LIKE 'ar%' DESC
LIMIT 10

Должны ли работать заказы по двоичному коду true / false для лайков, и если индексация должна быть выгодна от индекса

person exussum    schedule 14.12.2015