Mysql ценовой диапазон в пределах ценового диапазона?

Я разрабатываю сценарий недвижимости. В скрипте есть опция поиска, где пользователь может указать диапазон цен, например. user_price_low до user_price_high, и списки должны быть получены из базы данных, которая, например. db_price_high и db_price_low.

Я использовал оператор BETWEEN, пытаясь найти совпадения,

WHERE price_low BETWEEN '.$_REQUEST['minprice_buy'].' AND '.$_REQUEST['maxprice_buy']

но к моему удивлению...

Если у пользователя user_price_high = 60 и user_price_low = 20 И запись имеет db_price_low = 30 и db_price_high = 120

мой запрос недействителен в этом случае.

я попытался посмотреть MySql Query-Date Range в пределах диапазона дат Но соответствует ли это тому, что я хочу?


person chandan    schedule 07.09.2011    source источник
comment
Еще один php-пост, еще одна SQL-инъекция.   -  person Johan    schedule 07.09.2011
comment
что вы имеете в виду, что в БД есть price_low и price_high? Разве это не должно быть просто price? Покажите больше кода вместе с таблицей БД.   -  person Aaron W.    schedule 07.09.2011


Ответы (3)


Чандан, никогда не вводите функции $_* напрямую в запрос. Это дыра для SQL-инъекций.

Измените код на:

$min_price = mysql_real_escape_string($_REQUEST['minprice_buy']);
$max_price = mysql_real_escape_string($_REQUEST['maxprice_buy']);
$query = "SELECT whatever 
          FROM whichever 
          WHERE price_low BETWEEN '$min_price' AND '$max_price' ";
// Dont forget these quotes       ^          ^     ^          ^
// Or mysql_real_escape_string() will not work!.

Что касается вашего вопроса, измените запрос на что-то вроде:

WHERE '$min_price' BETWEEN price_low AND price_high 
  AND '$max_price' BETWEEN price_low AND price_high

Вы также можете рассмотреть:

WHERE ('$min_price' BETWEEN price_low AND price_high) 
  OR  ('$max_price' BETWEEN price_low AND price_high)

Здесь min_price и max_price не обязательно всегда должны находиться в диапазоне.

См.: Как работает SQL-инъекция из комикса Bobby Tables XKCD?

person Johan    schedule 07.09.2011
comment
Ваш ответ не совсем правильный, я не думаю. Оно должно быть включающим (ИЛИ), а не исключающим (И). - person Doug Kress; 07.09.2011
comment
Спасибо за быстрый ответ. Я попытался ввести запрос, как вы предложили, и все работает нормально. Однако я еще немного протестирую его, чтобы убедиться, что ошибок больше нет. Я ценю, что вы также напомнили мне о SQL-инъекции. Однако я сделал проверку с помощью $_REQUEST['minprice_buy'] = mysql_real_escape_string($_REQUEST['minprice_buy']); Разве это не будет хорошо? - person chandan; 07.09.2011
comment
Это просто усложнение без причины, я рекомендую код, подобный приведенному выше, его намного легче читать и понимать. Кроме того, нет необходимости заранее отклонять код, дайте запросу выполниться, иначе злоумышленник узнает, что вы тестируете, изучив разницу во времени в вашем коде и сосредоточив свою атаку на коде, для возврата которого потребовалось больше времени, т. е. на коде, где вы забыли поставить тест. - person Johan; 07.09.2011
comment
Здорово! Что происходит, когда user_low = 80, user_high = 200 и db_low = 64, db_high = 121, разве этот список не попадает в диапазон? Имеется в виду, что у строителя есть квартира с ним в пределах этого диапазона, верно? Мы думали о чем-то, где мы проверяем оба пути. ГДЕ (user_low между db_low И db_high) ИЛИ (user_high МЕЖДУ db_high И db_low) ИЛИ (db_low МЕЖДУ user_low И user_high) ИЛИ (db_high МЕЖДУ user_low И user_high) - person chandan; 07.09.2011
comment
@chandan, если вы хотите найти совпадение по этому, используйте последний вариант ответа. - person Johan; 07.09.2011

Если вы хотите проверить, есть ли у диапазонов какие-либо общие точки, вы должны использовать

WHERE greatest(price_low,user_price_low)<=least(price_high,user_price_high)

Если вы хотите проверить, находится ли диапазон пользователей во всем диапазоне, вы можете использовать
Неопределенное поведение для user_preice_low>user_price_high

WHERE user_price_low>=price_low && user_price_high<=price_high
person RiaD    schedule 07.09.2011
comment
в SQL функция max() так не работает, вам нужно использовать функцию наибольшего(). И если user_price_low = 50000 and user_price_high = 1, ваш запрос вернет true, даже если значения не попадают в диапазон. - person Johan; 07.09.2011
comment
@Johan: имена функций исправлены. для user_price_low = 50000 and user_price_high = 1 res первый запрос будет в порядке. Второй запрос вернет несколько строк, но его можно проверить на клиенте (я добавлю информацию) - person RiaD; 07.09.2011
comment
Я опустил -1, потому что верхняя строка верна, а нижняя - нет. Обратите внимание, что использование функции убьет любую возможность использования индекса. Что не сделает для счастливых запросов. - person Johan; 07.09.2011

так, как я понимаю, не должно быть

WHERE price_low >= '.$_REQUEST['minprice_buy'].' AND price_high <='.$_REQUEST['maxprice_buy']'

Проверьте свой ввод с помощью mysql_real_escape_string();, прежде чем использовать их в запросе, не используйте переменные $_GET, $_REQUEST, $_POST напрямую в любом запросе.

person Pheonix    schedule 07.09.2011
comment
-1, вы не можете оставить явную дыру для SQL-инъекций в таком ответе и ожидать, что получите голоса. Да, и ответ неверный WHERE X >= MIN AND y <= max не гарантирует, что (мин ‹ макс). - person Johan; 07.09.2011
comment
@ Йохан, почему в этом случае нужно гарантировать, что (мин‹макс)? - person Pheonix; 07.09.2011
comment
Потому что, если Min = 50000 и Max = 1, ни один из них не попадает в диапазон. - person Johan; 07.09.2011
comment
@Johan Йохан, разве нельзя предположить, что (min‹max), Min = 50000 и Max = 1 не имеют никакого смысла и не должны возвращать никаких результатов, я, вероятно, не вижу практического примера :-/ - person Pheonix; 07.09.2011