Проверка условия из другой таблицы при выборке данных.

phprus

Moderator
Команда форума
Проверка условия из другой таблицы при выборке данных.

Имеется база данных, в которой есть 3 таблицы:

1) users
id
key
day_request_limit
...

2) request_log
userid
time тип datetime
...

3) allowed_ip
userid
ip

Нам нужно проверить, есть ли в таблице "users" запись с определенным users.key, а если есть то необходимо проверить два условия. А именно количество записей в таблице request_log для этого userid за текущий день (поле time тип datetime) должно быть меньше чем значение поля users.day_request_limit (это нужно сигнализировать дополнительным полем в результате, например выставить его в значение 1).
И еще надо проверить входит ли IP в список разрешенных ip из таблицы allowed_ip для данного userid (результат так-же нужно отображать установкой еще одного поля результата, например в значение 1)

Проверка первого условия решается следующим запросом:
[sql]
SELECT
users.*,
COUNT(request_log.userid) as current_day_request_count
FROM `users`
LEFT JOIN `request_log` on (users.id = request_log.userid)
WHERE `key` = '***'
AND DATEDIFF(CURRENT_DATE(), IFNULL(request_log.time, CURRENT_DATE())) = 0
GROUP BY request_log.userid
[/sql]

А вот как проверять второе условие я не знаю.
По этому не могли бы вы подсказать, как мне добавить проверку второго условия? Желательно сделать это одним запросом, ну или с использованием подзапросов.

Версия Mysql - 5.0.
 

Bitterman

Новичок
Сколько разрешенных IP соответствуют одному юзеру? Если несколько, то прописывается ли во второй таблице ip, с которого был сделан запрос?
 

phprus

Moderator
Команда форума
Сколько разрешенных IP соответствуют одному юзеру?
От одного до бесконечности (Хотя до бесконечности это громко сказано, но заранее не определено сколько разрешенных IP. Их может быть сколько угодно)

прописывается ли во второй таблице ip, с которого был сделан запрос
Нет. Но даже если бы и был, то это врядли бы помогло, так как разрешенные ip могут меняться, и не со всех разрешенных ip могут быть сделаны запросы до момента проверки.

Следует так-же учитывать, что на момент выполнения этой проверки в таблице request_log может вообще не быть записей за текущий день (именно по этому у меня в запросе используется IFNULL в WHERE-блоке)
 

phprus

Moderator
Команда форума
Bitterman
Хм, а где тогда прописываются ip, с которых делает запрос пользователь
Истории ip у нас нету. А текущий ip у нас хранится в виде переменной в программе и может быть подставлен в запрос.
У нас есть только таблица-список разрешенных ip.

В общем не найдя решения без вложенных запросов я сделал так:
[sql]
SELECT
users.id as id,
IF( COUNT(request_log.userid) < users.day_request_limit, 0, 1) as day_request_limit_is_overflow,
(
SELECT COUNT(ip) FROM allowed_ip WHERE allowed_ip.userid = users.id AND ip = '<тут подставляется ip с которого сделан запрос>'
) as ip_is_allowed
FROM `users`
LEFT JOIN `request_log` on (users.id = request_log.userid)
WHERE
`key` = '<тут ключ>'
AND
DATEDIFF(CURRENT_DATE(), IFNULL(request_log.time, CURRENT_DATE())) = 0

GROUP BY request_log.userid
[/sql]
Вродебы этот запрос работает правильно.
 

Bitterman

Новичок
Про ip в переменной в изначальных условиях речи не было.
По поводу запроса: а если заменить подзапрос на
[sql]
LEFT JOIN allowed_ip ON allowed_ip.userid=users.id AND allowed_ip.ip='<ip>'
[/sql]
?
Соответственно в наборе возвращаемых полей COUNT(allowed_ip.ip), что будет возвращать либо 1, либо NULL. Так будет работать?
 

phprus

Moderator
Команда форума
Bitterman
Про ip в переменной в изначальных условиях речи не было.
Когда я писал вопрос я думал, что будет понятно, что IP у нас существует в виде переменной в программе и может быть подставлен в запрос. Но видимо я ошибался.

Так будет работать?
Работает.
COUNT(allowed_ip.ip), что будет возвращать либо 1, либо NULL
А почему COUNT должен возвращать NULL, а не просто 0 ?
 

phprus

Moderator
Команда форума
Bitterman
Мануал говорит:
> Returns a count of the number of non-NULL values in the rows retrieved by a SELECT statement. The result is a BIGINT value.

Но про JOIN вы подсказали правильно. Ваш вариант работает. Спасибо.
 
Сверху