Проблема сортировки MySQL для автозаполнения - PullRequest
4 голосов
/ 22 декабря 2010

У меня есть автозаполнение на моем сайте, где пользователь входит в класс в своей школе.Затем он предоставляет раскрывающийся список Классов, в которых есть слова, которые они вводили где-то в своих полях.В таблице Classes есть поля Class_ID, Term_ID, Department_Code, Course_Code, Class_Code, Course_Title, Instructor, в которых все ищутся по терминам, которые вводит пользователь. Предположим, использование вводит слова «international econ».Затем он будет искать эти два термина в полях следующим образом:

SELECT Class_ID, Department_Code, Course_Code, Class_Code, Course_Title, Instructor FROM Classes AND ((REPLACE(REPLACE(REPLACE(CONCAT(Department_Code, Course_Code, Class_Code), '-', ''), '(', ''), ')', '') LIKE '%international%' OR Instructor LIKE '%international%' OR Course_Title LIKE '%international%') AND (REPLACE(REPLACE(REPLACE(CONCAT(Department_Code, Course_Code, Class_Code), '-', ''), '(', ''), ')', '') LIKE '%econ%' OR Instructor LIKE '%econ%' OR Course_Title LIKE '%econ%')) LIMIT 10

Две быстрые заметки по этому запросу - я делаю REPLACE () и CONCAT (), чтобы пользователи могли вводить depts / курсы / секциикак единое целое, например, ECON-101 (кафедра и курс вместе).Кроме того, я вставил значительно упрощенный запрос, который не учитывает способ сортировки и группировки, который я сейчас выполняю.

Однако мой вопрос касается того, как я могу отсортировать результаты.Я хочу, чтобы записи, соответствующие Class_Code, возвращались вверху, затем Course_Code, затем Dept, затем Course_Title, наконец, prof.Другими словами, я хочу, чтобы результаты сортировались по количеству спецификаций, предоставляемых пользователем при автозаполнении.Если бы они знали Class_Code, я бы поэтому хотел, чтобы он был наверху.

Я не могу придумать способ сделать этот вид, который не требует большого запроса.Пока что я могу думать только о том, чтобы сделать это, сопоставляя несколько сравнений LIKE для каждого термина с каждым полем, а затем ЗАКАЗЫВАЯ по этим псевдонимам.Это эквивалентно пятикратному количеству слов, которые пользователь вводит в автозаполнение. Другими словами, огромный уродливый запрос.

Существует ли простой и эффективный способ выполнить такую ​​сортировку?Если бы существовало что-то вроде функции INSTR (), которая брала для поиска несколько строк, я легко могла бы просто сравнить все слова в автозаполнении с каждым полем и всегда сортировать по 5 псевдонимам, созданным этим.

Любые предложения приветствуются, даже если это общее предложение, выходящее за рамки вопроса.Однако заранее хочу отметить, что я не готов использовать что-то вроде FULLTEXT или поисковую систему, подобную Sphinx, потому что я не чувствую, что она подходит для неинтенсивного, быстрого запроса, подобного этому.Кроме того, я не открыт для реструктуризации моей базы данных.Поэтому я хотел бы сделать это с хорошим запросом MySQL о том, что у меня уже есть.

Заранее спасибо ..

Ответы [ 3 ]

1 голос
/ 22 декабря 2010

Рассматривали ли вы использование оператора UNION?Вы можете разделить различные запросы в их собственном операторе SELECT, а затем объединить их все вместе с помощью UNION.Это автоматически сохранит их в нужных вам группах - в том порядке, в котором вы выполняете операторы SELECT.

Это может сделать ваш запрос больше, но должно быть эффективным.

0 голосов
/ 22 декабря 2010

вы можете сделать

order by case when code  like '%blabla%' then 0 else 1 end
        ,case when dept  like '%blabla%' then 0 else 1 end
        ,case when title like '%blabla%' then 0 else 1 end

Таким образом, все совпадения в коде будут отсортированы до совпадений в отделе и т. Д.

Обновлено для комментария Если я понимаюПоследний комментарий правильно, вы обеспокоены тем, что вы будете повторять сложные выражения в запросе?В этом случае вы можете либо заключить замену / конкатат и т. Д. В производную таблицу (см. Ниже), либо создать представление.

select *
  from (select class_code
              ,department_code
              ,department_code
              ,replace(concat(...)) as code
              ,replace(concat(...)) as dept
              ,replace(concat(...)) as title
          from classes
         where class_code      like '%blabla%'
            or department_code like '%blabla%'
            or class_title     like '%blabla%'
       ) as wrapped
 order by case when code  like '%blabla%' then 0 else 1 end
         ,case when dept  like '%blabla%' then 0 else 1 end
         ,case when title like '%blabla%' then 0 else 1 end

Просто убедитесь, что выполняете фактический поиск по реальным столбцам, а не по вычисленным столбцам, чтобы убедиться, что mysql может использовать индексы.

Кстати, mysql не волнуетесли запрос длинный и сложный, пока фильтры и объединения выглядят «просто».

0 голосов
/ 22 декабря 2010

ORDER BY принимает несколько значений, поэтому просто перечислите столбцы в нужном вам порядке:

SELECT column_name(s)
FROM table_name
ORDER BY column_name(s) ASC|DESC

Другая возможность, которую вы можете попробовать, - написать функцию генератора SQL. Иногда, если сценарий очень уродливый и должен измениться, наличие функции, генерирующей сценарий в модульном формате, может облегчить просмотр происходящего.

...