У меня есть существующий сайт, чья БД не разработана правильно и содержит много записей, поэтому мы не можем изменить структуру БД.Пересечение MySQL
База данных по текущему выпуску в основном содержит 4 таблицы, пользователей, вопросы, варианты и ответы. Существует стандартный набор вопросов и вариантов, но для каждого пользователя есть одна строка в таблице ответов для каждого набора вопросов и опций. Структура БД и данные примера доступны по адресу SQL fiddle.
Теперь, как новое требование расширенного поиска, мне нужно найти пользователей, применяя несколько фильтров поиска. Пример ввода и ожидаемого результата приводится в комментариях к SQL Fiddle.
Я попытался применить все типы соединений, пересечение, но он всегда терпит неудачу. Может кто-то, пожалуйста, помогите мне написать правильный запрос, желательно облегченный/оптимизированный объединять, поскольку БД содержит множество записей (10000+ пользователей, 100+ вопросов, 500+ опций и 500000+ записей в таблице ответов)?
EDIT: На основе двух ответов, я использовал следующий запрос
SELECT u.id, u.first_name, u.last_name
FROM users u
JOIN answers a ON a.user_id = u.id
WHERE (a.question_id = 1 AND a.option_id IN (3, 5))
OR (a.question_id = 2 AND a.option_id IN (8))
GROUP BY u.id, u.first_name, u.last_name
HAVING
SUM(CASE WHEN (a.question_id = 1 AND a.option_id IN (3, 5)) THEN 1 ELSE 0 END) >=1
AND SUM(CASE WHEN (a.question_id = 2 AND a.option_id IN (8)) THEN 1 ELSE 0 END) >= 1;
Обратите внимание: В реальной базе данных, столбцы user_id
, question_id
и option_id
из answers
таблиц проиндексированы.
Выполненный запрос, указанный на SQL Fiddle.
SQL Fiddle для ответа dnoeth.
SQL Foddle для ответа calcinai.
Спасибо @dnoeth, +1 за рабочий запрос. Должен признаться, что на данный момент я не понимаю, что вы написали после «HAVING». Я должен пройти через документы немного. Я применим ваш и @calcinai andwer и соглашусь с тем, что когда-либо более оптимизировано.Еще раз спасибо за ответ и, что более важно, новое для меня (SUM/CASE WHEN и т. Д.) –
@ Kapil Sharma: Конечно, моя версия более эффективна :-) Легко добавить дополнительные условия, добавить новое условие для WHERE/HAVING вместо другого соединения. Что касается логики: проверьте, если каждое условие имеет значение TRUE хотя бы один раз – dnoeth
Я тоже чувствую себя так, как в реальном времени, может быть 30-50 фильтров и 30-50 соединений, очевидно, будут убивать сервер БД, особенно когда запрос случается слишком часто. Тем не менее нам нужно реализовать некоторый бенчмарк в реальной БД с 500000+ записями. Пожалуйста, дайте мне немного времени, это может занять пару часов. Я бы принял оба ответа, но SO не допускал этого. –