Выбор записи из БД (нужен совет)

#1 26 сентября 2012 в 21:34
Возник еще один вопрос с работой с БД.
Нужен совет, как организовать порядок запросов:
Вообщем есть кое-какая голосовалка и суть работы в следующем:

1. При открытии страницы из базы данных выбирается случайная запись за которую нужно проголосовать.
2. После голосования в другую таблицу записывается id записи. время, и ip проголосовавшего.
3. При следующем открытии страницы опять выбирается случайная запись. и т.д.

Нужно чтоб не было повторов голосования одного ip адреса за одну и ту же запись ...
Ясно что при открытии страницы и выборе из БД записи нужно проверить не голосовал ли за эту запись пользователь с текущим ip…
Как выбрать из таблицы запись, ту за которую пользователь с текущим ip не голосовал. ...
(как делать запросы я знаю… логики не пойму)
#2 26 сентября 2012 в 23:00
привязывать к ip неправильно так как вы сразу блокируете части пользователей за nat возможность голосовать после первого проголосовавшего из этой серой сети
нужно по кукам или еще както идентифицировать
и для понятности вы не сказали — у вас все имеют возможность голосовать или только зарегистрированные
#3 26 сентября 2012 в 23:34
Да, все голосуют. Интересует только по ip, проблем это не создаст, тем более записи ip хранятся только 24 часа.
Допустим делаю случайную быборку записи из БД с id = 1, затем проверяю голосовал ли за эту запись пользователь.
Если нет хорошо — загружаем запись, а если да? Не перезагружать же страницу… можно конечно вывести запись, что вы уже тут голосовали, но нужно загрузить именно ту за которую не голосовали
#4 27 сентября 2012 в 01:10
Каждый раз как берем записи из базы нужно проверять, не голосовал ли уже за эту запись пользователь. Можно одним запросом, надо делать как то так:
  1.  
  2. sql = "SELECT f.*, t.*
  3. FROM `1_таблица` f
  4. LEFT JOIN `2_таблица` t ON t.field_id = f.id
  5. WHERE t.ip != 'сюда вставляем ip пользователя'";
  6.  
Здесь подразумевается, что во второй таблице есть поле field_id, содержащий id записи с первой таблицы, и поле ip, содержащий ip пользователя.
Думаю, суть понятна.
#5 27 сентября 2012 в 06:02
Марат, извиняюсь что тебя поправляю, говоришь все как надо, но не разумней ли для начала показать новичку простой запрос, а уже потом склейку таблиц?
#6 27 сентября 2012 в 07:20

Здесь подразумевается, что во второй таблице есть поле field_id, содержащий id записи с первой таблицы, и поле ip, содержащий ip пользователя.

Марат

Предчувствую тут косяк из-за того, что в таблице_2 одному id таблицы_1 могут соответствовать несколько строк
#7 27 сентября 2012 в 08:10

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

Максим Шорин
Да, можно и так. Но вроде TC хочет, чтобы если пользователь голосовал за запись, то запись больше не должна ему показываться. Получается при первом открытии страницы нужно всё равно проверить голосовал ли он уже. Иначе он может вернуться и через час и увидит запись, за которую уже голосовал.

Предчувствую тут косяк из-за того, что в таблице_2 одному id таблицы_1 могут соответствовать несколько строк

Ленивый
Упс. Точно. Устраняется просто. Добавляем в конец запроса
  1. GROUP BY f.id
#8 27 сентября 2012 в 08:20

Да, можно и так. Но вроде TC хочет, чтобы если пользователь голосовал за запись, то запись больше не должна ему показываться. Получается при первом открытии страницы нужно всё равно проверить голосовал ли он уже. Иначе он может вернуться и через час и увидит запись, за которую уже голосовал.

Марат

имел ввиду следущее:
выборка из таблицы
получение результата
выбрка из результата нужного значения
цикл
проверка
конец цикла
#9 27 сентября 2012 в 08:36
Максим Шорин, всё верно. Можно и так. У любой задачи есть несколько вариантов решения.
Пункт "проверка" подразумевает ещё одно обращение к БД, ко второй таблице. Что оптимальнее один сложный запрос или 2 простых, это решать тому, кто пишет. В любом случае, можно написать оба варианта и проверить, что быстрее выполняется. Но я бы сделал одним запросом. Во-первых, более короткий код, во-вторых, всё равно, думаю, один запрос(хоть и сложный) будет быстрее.
В общем, решение есть. ТС проверять и выбирать, что лучше )
#10 27 сентября 2012 в 08:41

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

Максим Шорин

имел ввиду следущее:
выборка из таблицы
получение результата
выбрка из результата нужного значения
цикл
проверка
конец цикла

Максим Шорин

МЕГА-нерационально!!! Не надо новичков такому учить!!! :)))
#11 27 сентября 2012 в 09:15
Марат,

Упс. Точно. Устраняется просто. Добавляем в конец запроса
Код PHP:

GROUP BY f.id

Марат

не уверен…
#12 27 сентября 2012 в 09:26
  1. SELECT f.*, t. *
  2. FROM `cms_fotos` f
  3. LEFT JOIN `cms_golosa` t ON t.foto_id = f.id AND t.user_ip != ip_юзера
  4. ORDER BY rand( )
  5. LIMIT 1
  6.  
вернёт ОДНУ СЛУЧАЙНУЮ запись из таблицы cms_fotos, для которой в таблице cms_golosa НЕ БУДЕТ строки содержащей id этой записи в поле foto_id и ip юзера в поле user_ip
#13 27 сентября 2012 в 11:20

LEFT JOIN `2_таблица` t ON t.field_id = f.id

Марат
можно воспользоваться INNER JOIN, если я правильно понял задачу.

ORDER BY rand( )

Ленивый
очень ресурсоемкая операция
#14 27 сентября 2012 в 11:28
Fuze,

очень ресурсоемкая операция

Fuze
Как обычно в своём репертуаре!!! :))))
не проще написать менее ресурсоёмкую операцию!? Все будут только благодарны!!! А так какой прок от Вашего сообщения??
#15 27 сентября 2012 в 11:55

Как обычно в своём репертуаре!!! :))))

Ленивый
поясните

не проще написать менее ресурсоёмкую операцию!?

Ленивый

можно воспользоваться INNER JOIN, если я правильно понял задачу.

Fuze
Прочитать выше религия не позволяет?
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.