Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737 Форумы портала PHP.SU :: MySQL - вложенные запросы
Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013
Помог: 0 раз(а)
Доброго времени суток, уважаемые форумчане)
Я пишу модуль голосований для своего сайта. Буквально вчера мне понадобилось вывести голосования в категорию не голосованых. То есть, что-бы пользователю выводились только вопросы на которые он еще не давал ответа.
Но, возвращаемый результат более чем не коректен. То есть, убирается только один голосованый опрос, а остальные выводятся все равно. Если же убрать с вырежения EXISTS - возвращается ошибка под запроса, с EXISTS же под запрос эдентичен так, если-бы в конец добавить LIMIT 1. Но, мне нужно что-бы были исключены все опросы за которые текущий пользователь уже голосовал. Я слышал, что в MySQL уже имеются циклы такие как WHILE, LOOP и тп. Но раскрытую инструкцию по их использованию я со своим корявим г* интернетом я найти самостоятельо не могу. По этому у меня огромная прозьба, спецы, подскажите пльз с кодом и выше упомянутой литературки тоже подкиньте если есть. За ранее Вам благодарен, спасибо)
PS
Я бы мог все решить с помощью PHP но, хочется сделать все красиво и правильно, помогите, а)Отредактировано модератором: Мелкий, 11 Апреля, 2013 - 14:29:22
Мелкий
Отправлено: 11 Апреля, 2013 - 14:33:09
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Ja_kazanova пишет:
что-бы пользователю выводились только вопросы на которые он еще не давал ответа.
Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013
Помог: 0 раз(а)
Извините, решение явилось прям, как Менделееву во сне. Вот правильный код (кому интересно)
SELECT * FROM `ac_opros` WHERE `time_end` > UNIX_TIMESTAMP() AND IF((SELECT COUNT(*) FROM `ac_opros_variant_set`) > 0, `id` NOT IN (SELECT `id_file` FROM `ac_opros_variant_set` WHERE `id_user` = '{$user -> id}' OR `ip` = '{$user -> ip}'), `id` <> '0')
Благодарю все за внимание и желание помочь. Тему можно крыть) (Добавление)
Мелкий пишет:
Ja_kazanova пишет:
что-бы пользователю выводились только вопросы на которые он еще не давал ответа.
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Ja_kazanova пишет:
Спасибо но, JOIN(ов) я стараюсь избегать
Отчего же?
Тогда вам и подзапросы использовать никак нельзя. Некоторые подзапросы оптимизатор переписывает в join, потому что это заметно эффективнее.
----- PostgreSQL DBA
Ja_kazanova
Отправлено: 11 Апреля, 2013 - 15:45:12
Новичок
Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013
Помог: 0 раз(а)
Мелкий пишет:
Ja_kazanova пишет:
Спасибо но, JOIN(ов) я стараюсь избегать
Отчего же?
Тогда вам и подзапросы использовать никак нельзя. Некоторые подзапросы оптимизатор переписывает в join, потому что это заметно эффективнее.
От чего-же? В приведенном мною примере используется 2 под запроса + проверка на наличие записей в таблице статистики. Потому как если в выше упомянутой таблице статистики нет ни одной записи, mysql_num_rows(mysql_query(ваш код)) // = 0 в любом случае
Мелкий
Отправлено: 11 Апреля, 2013 - 15:59:54
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Ja_kazanova пишет:
Потому как если в выше упомянутой таблице статистики нет ни одной записи, mysql_num_rows(mysql_query(ваш код)) // = 0 в любом случае
Докажите показав, как пробовали. Это не так для предложенного запроса и структуры таблиц. В результате будут все опросы, в которых не участвовал пользователь. Если ни в одном не участвовал - все опросы.
Я уверен, что мой запрос вы изменили (что логично), но не в том месте.
PS: которая из 3 таблиц - статистика? undefined variable
----- PostgreSQL DBA
Ja_kazanova
Отправлено: 11 Апреля, 2013 - 16:30:05
Новичок
Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013
Помог: 0 раз(а)
Мелкий пишет:
Ja_kazanova пишет:
Потому как если в выше упомянутой таблице статистики нет ни одной записи, mysql_num_rows(mysql_query(ваш код)) // = 0 в любом случае
Докажите показав, как пробовали. Это не так для предложенного запроса и структуры таблиц. В результате будут все опросы, в которых не участвовал пользователь. Если ни в одном не участвовал - все опросы.
Я уверен, что мой запрос вы изменили (что логично), но не в том месте.
PS: которая из 3 таблиц - статистика? undefined variable
Право, Вы слишком высокого мнения о себе)
У меня нет ни времени, ни смысла, ни желания спорится с Вами, милейший. По сему в кратко и по сути.
Ничего и не пришлось изменять коме <> на NOT IN в своем же посте (№ 1), что в свою очередь схоже с циклами foreach, for, while в php.
Теперь залейте все предоставленные мной таблицы и сосчитайте количество не голосованых пользователем опросов при условии, что та самая таблица статистики залита но пуста то есть, не содержит не одной записи.
Результатом выполнения ниже представленного кода при условии подстановки Вашего куска
echomysql_num_rows(mysql_query("SELECT * FROM `ac_opros` WHERE `time_end` > UNIX_TIMESTAMP() AND IF((SELECT COUNT(*) FROM `ac_opros_variant_set`) > 0, `id` NOT IN (SELECT `id_file` FROM `ac_opros_variant_set` WHERE ".(isset($user->person)?"`id_user` = '{$user -> id}' OR ":" `open` = '1' AND")." `ip` = '".$_SERVER['REMOTE_ADDR']."'))"));// = Верное количество не голосованных опросов
`ac_opros` - сам вопрос и его описание,
`ac_opros_variant` - варианты ответов,
`ac_opros_variant_set` - собственно та самая статистика, которую Вы, как ни странно в упор не заметили.
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Ja_kazanova пишет:
`ac_opros_variant_set` - собственно та самая статистика, которую Вы, как ни странно в упор не заметили.
Ja_kazanova пишет:
Учет ответов */ CREATE TABLE IF NOT EXISTS `ac_opros_variant_set`
Ja_kazanova пишет:
Таблица статистических опросов */ CREATE TABLE IF NOT EXISTS `ac_opros`
Под словом "статистика" вы могли подразумевать как ту, так и другую.
Ja_kazanova пишет:
Теперь залейте все предоставленные мной таблицы и сосчитайте количество не голосованых пользователем опросов при условии, что та самая таблица статистики залита но пуста то есть, не содержит не одной записи.
$rPrepareUserQuestions=$rDB->prepare("SELECT `ac_opros`.* FROM `ac_opros` LEFT JOIN `ac_opros_variant_set` ON id_user=? AND `ac_opros`.id=`id_file` WHERE `id_file` IS NULL");
echo'Непройденных опросов у пользователя 2: '.$rPrepareUserQuestions->rowCount();
Цитата:
Непройденных опросов у пользователя 1: 4
Непройденных опросов у пользователя 2: 5
Ja_kazanova пишет:
не пришлось изменять коме <> на NOT IN
Мелкий пишет:
Я уверен, что мой запрос вы изменили (что логично), но не в том месте.
(Добавление)
Ja_kazanova пишет:
хочется сделать все красиво и правильно, помогите, а)
Ja_kazanova пишет:
Спасибо но, JOIN(ов) я стараюсь избегать
Мелкий пишет:
Отчего же?
Ja_kazanova пишет:
У меня нет ни времени, ни смысла, ни желания спорится с Вами, милейший.
Так вы определитесь, хотите вы делать красиво и правильно - для этого нужна дискуссия.
Подзапросы, особенно в mysql до 5.6 - штука медленная. Заметно медленнее джойнов. Запустите свой запрос на мелкой табличке, ну этак, с 10тыс опросов и с 100тыс ответов пользователей. Мелкая же табличка, не правда ли?
Ну а если вы передумали делать правильно - то тема действительно закрыта, приношу извинения, что напрасно трачу ваше время. С радостью подскажем в своё время, почему выборки тормозят.
----- PostgreSQL DBA
Ja_kazanova
Отправлено: 11 Апреля, 2013 - 17:30:55
Новичок
Покинул форум
Сообщений всего: 15
Дата рег-ции: Апр. 2013
Помог: 0 раз(а)
Мелкий, если в первом посте ваш код тогда я с вами полностью согласен. Но постольку поскольку там именно мой код без использования излюбленного вами JOIN(а) и вопрос как таковой уже давно исчерпан, тогда к чему эти танцы с бубном? Кому, чем и главное что вы пытаетесь доказать? Перед вложенным поиском строк имеет место проверка на заполненность которая была произведена посредством связки IF/COUNT, что и было сделано мной. И к чему те километры кода которые вы выложили в пред ведущем посте демонстрируя этим самым свою не компетентность. Ибо не нужен гектар кода там, где достаточно одного корректного предложения. Это мое имхо + тесты на производительность тоже на моей стороне)
Всего Вам доброго, прощевайте)
esterio
Отправлено: 11 Апреля, 2013 - 18:10:01
Активный участник
Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012 Откуда: Украина, Львов
Помог: 127 раз(а)
Ja_kazanova
Думаю Вам не стоит спорить с Мелкий. По сути
уже бистрее и проще. И если query вернет false, то словите error. И вместо таких замеров сделайте EXPLAIN - он Вам подскажет где Вы ошиблись.
Мелкий
Отправлено: 11 Апреля, 2013 - 21:14:28
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Ja_kazanova пишет:
Кому, чем и главное что вы пытаетесь доказать?
Ничего не пытаюсь доказать, я пытаюсь выяснить вашу аргументацию вот этого:
Ja_kazanova пишет:
Спасибо но, JOIN(ов) я стараюсь избегать
Разумеется, я могу чего-то не знать, но ваша категоричная позиция меня удивляет.
Ja_kazanova пишет:
Перед вложенным поиском строк имеет место проверка на заполненность которая была произведена посредством связки IF/COUNT, что и было сделано мной.
Ну и какая проблема? Есть как минимум ещё тройка способов это сделать по-разному.
Ja_kazanova пишет:
к чему те километры кода
Иллюстрация работоспособности, ведь вы утверждаете:
Ja_kazanova пишет:
возвратит 0 не глядя на то что, опросы таки имеются в ассортименте
Что не соотносится с действительностью. Если вы обратите внимание, 99% кода - это создание таблиц и их заполнение тестовой информацией.
Я решил, что полный автономный пример достаточно проиллюстрирует "Теперь залейте все предоставленные мной таблицы ..."
Ответьте всё-таки на вопрос, почему вы избегаете джойнов? Это инструмент, позволяющей базе делать то, что делать она умеет хорошо. Это единственное, что я хочу от вас узнать.
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.