SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 05.04.2011 12:57:39

jam
Участник
Зарегистрирован: 05.04.2011
Сообщений: 3

выбрать из одной таблицы значения, которых нет в другой

Здравствуйте.
У меня есть две таблицы, в которых я храню загадки и ответы пользователей на них:
riddles (z_id, v_id), здесь z_id - уникальное значение, автоинкремент, а v_id - айди автора загадки, может повторяться.
answers (z_id, v_id), здесь z_id - номер загадки, v_id - айди человека, давшего ответ. в этой таблице уникальны пары (z_id, v_id), т.к. на одну загадку человек может ответить только один раз.
Требуется выдать человеку 10 загадок, на которые он еще не давал ответ. Я изначально сделал это так:

SELECT * FROM riddles WHERE z_id NOT IN (SELECT z_id FROM answers WHERE v_id='.$vid.') LIMIT 10;

Такой запрос выполняется медленно. Плюс еще сортировка, например по рейтингу, или случайная выборка, и время запроса увеличивается в разы. Конечный запрос был такой:
SELECT * FROM riddles WHERE v_id <> '.$vid'. AND z_id NOT IN (SELECT z_id FROM answers WHERE v_id='.$vid.') ORDER BY reyt LIMIT '.$cnt.', 10;

Время обработки больше 5 секунд.
Собственно вопросы:
1) правильно ли я понимаю последовательность работы MySql: сначала берутся все строки из riddles, сортируются по reyt, далее для каждой строки делается запрос v_id <> '.$vid'. AND z_id NOT IN (SELECT z_id FROM answers WHERE v_id='.$vid.'), строка либо отсекается от выборки, либо остается. и после этого выбирается из результата 10 строк. Последовательность такая?
2) можно ли добиться того же результата, существенно уменьшив время обработки запроса? если да, то в какую сторону копать, с помощью каких операторов правильно делат подобные запросы?

пока что этот запрос убрал из скрипта, делаю просто выборку из 10 загадок, а потом для каждой отдельный запрос, отвечал ли на неё пользователь

Спасибо

Неактивен

 

#2 05.04.2011 16:10:59

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: выбрать из одной таблицы значения, которых нет в другой

jam написал:

1) правильно ли я понимаю последовательность работы MySql: сначала берутся все строки из riddles, сортируются по reyt, далее для каждой строки делается запрос v_id <> '.$vid'. AND z_id NOT IN (SELECT z_id FROM answers WHERE v_id='.$vid.'), строка либо отсекается от выборки, либо остается. и после этого выбирается из результата 10 строк. Последовательность такая?

Сначала для каждой строки делается запрос v_id <> '.$vid'. AND z_id NOT IN (SELECT z_id FROM answers WHERE v_id='.$vid.'), строка либо отсекается от выборки, либо остается.
Полученный результат сортируется по reyt.
После этого выбирается из результата 10 строк.

Отсюда понятно почему без сортировки запрос работает существенно быстрее - его выполнение прекращается после 10 найденных результатов.


В MySQL неправильно работают подзапросы в конструкции in. Они выполняются для каждой строки основного запроса, даже если являются независимыми (как в данном случае). Решение переписать запрос через JOIN

SELECT r.* FROM riddles r left join (SELECT z_id FROM answers WHERE v_id='.$vid.') a using(z_id) WHERE v_id <> '.$vid'. AND a.z_id is null ORDER BY reyt LIMIT '.$cnt.', 10;

Неактивен

 

#3 05.04.2011 18:03:20

jam
Участник
Зарегистрирован: 05.04.2011
Сообщений: 3

Re: выбрать из одной таблицы значения, которых нет в другой

спасибо за ответ, проверил, летает. буду разбираться с JOIN, по началу довольно трудно въехать, как его правильно использовать smile

т.е. насколько я понял, при использовании IN у меня внутренний подзапрос выполнялся для каждой строки внешнего, а при использовании JOIN он выполняется только один раз и его результат сравнивается с результатом внешнего запроса. Правильно?

Неактивен

 

#4 05.04.2011 23:04:04

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: выбрать из одной таблицы значения, которых нет в другой

Да

Неактивен

 

#5 06.04.2011 07:06:04

jam
Участник
Зарегистрирован: 05.04.2011
Сообщений: 3

Re: выбрать из одной таблицы значения, которых нет в другой

Благодарю за ответы!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson