Sql поиск по нескольким полям, когда какое-то поле может быть пустым

drkrol

Постоялец
Регистрация
6 Мар 2016
Сообщения
112
Реакции
11
Здравствуйте. Пытаюсь сделать фильтрацию. Есть 3 значения "имя", "дата от", "дата до".
Если убрать всё лишнее, у меня вот такая картина:

PHP:
$sql = 'SELECT * FROM main WHERE nameclient LIKE :who AND (datestart BETWEEN :datestart AND :dateend) ';
$pdo_statement->bindValue(':who',$name, PDO::PARAM_STR);
$pdo_statement->bindValue(':datestart',$dstart, PDO::PARAM_STR);
$pdo_statement->bindValue(':dateend',$dend, PDO::PARAM_STR);
$pdo_statement->execute();
$result = $pdo_statement->fetchAll();
?>

переменные who, dstart и dend я получаю из формы.
Проблема состоит в том, что какое-то из полей формы, будь это имя или диапазон дат, может быть не заполнено. Сейчас, в моём случае, если какое-то из полей не заполнить, то вернётся пустой результат.
Подскажите, как сделать, чтобы sql игнорировал пустые поля?
 
Надо переписать запрос, потому что в случае пустых полей, у тебя проблема будет не в значениях, а в самом запросе.

PHP:
<?php
$sql = 'SELECT * FROM main WHERE 1=1 ';
if (!empty($name))
    $sql .= 'AND nameclient LIKE :who';
if (!empty($dstart) && !empty($dend))
    $sql .= 'AND (datestart BETWEEN :datestart AND :dateend) ';
elseif (!empty($dstart)
    $sql .= 'AND (datestart >= :datestart)';
elseif (!empty($dend)
    $sql .= 'AND (dateend <= :dateend)';

$pdo_statement->bindValue(':who',$name, PDO::PARAM_STR);
$pdo_statement->bindValue(':datestart',$dstart, PDO::PARAM_STR);
$pdo_statement->bindValue(':dateend',$dend, PDO::PARAM_STR);
$pdo_statement->execute();
$result = $pdo_statement->fetchAll();
?>
 
костыль какой-то получается. У меня таких полей будет 20: и цена, и цвет, и кол-во. Разве нет в Php такой функции, чтобы без if всё нормально работало?
 
Это не костыль, а нормальная реализация фильтра, подобного вашему. В PHP нету понятия какая пятка у вас сейчас чешется. Если вам нужно сделать РАЗНЫЕ запросы - то уж извините, PHP не может додумать за вас бизнес логику приложения.

Используйте ORM, они эту реализацию спрячут в себе, но, грубо говоря, она будет подобна той что я указал. К примеру в AR в Yii2 есть метод ->addFilterWhere() который убирает это условие из построителя запроса, если в параметрах передан null / false.
 
костыль какой-то получается. У меня таких полей будет 20: и цена, и цвет, и кол-во. Разве нет в Php такой функции, чтобы без if всё нормально работало?
это не костыль, а правильное обращение к БД и в этом нет ничего страшного.
 
  • Нравится
Реакции: BaBL
Надо переписать запрос, потому что в случае пустых полей, у тебя проблема будет не в значениях, а в самом запросе.

PHP:
<?php
$sql = 'SELECT * FROM main WHERE 1=1 ';
if (!empty($name))
    $sql .= 'AND nameclient LIKE :who';
if (!empty($dstart) && !empty($dend))
    $sql .= 'AND (datestart BETWEEN :datestart AND :dateend) ';
elseif (!empty($dstart)
    $sql .= 'AND (datestart >= :datestart)';
elseif (!empty($dend)
    $sql .= 'AND (dateend <= :dateend)';

$pdo_statement->bindValue(':who',$name, PDO::PARAM_STR);
$pdo_statement->bindValue(':datestart',$dstart, PDO::PARAM_STR);
$pdo_statement->bindValue(':dateend',$dend, PDO::PARAM_STR);
$pdo_statement->execute();
$result = $pdo_statement->fetchAll();
?>

Эм, а привязывать значения разве не надо только в том случае, если они используются в запросе? о_О
Т.е. по идее так как-то:

PHP:
<?php
$sql = 'SELECT * FROM main WHERE 1=1 ';
if (!empty($name)) {
    $sql .= 'AND nameclient LIKE :who';
    $pdo_statement->bindValue(':who',$name);
}
if (!empty($dstart) && !empty($dend)) {
    $sql .= 'AND (datestart BETWEEN :datestart AND :dateend) ';
    $pdo_statement->bindValue(':datestart',$dstart);
    $pdo_statement->bindValue(':dateend',$dend);
}
elseif (!empty($dstart) {
    $sql .= 'AND (datestart >= :datestart)';
    $pdo_statement->bindValue(':datestart',$dstart);
}
elseif (!empty($dend) {
    $sql .= 'AND (dateend <= :dateend)';
    $pdo_statement->bindValue(':dateend',$dend);
}
$pdo_statement->execute();
$result = $pdo_statement->fetchAll();
?>

P.S. PDO:: PARAM_STR по умолчанию используется, т.е. явно задавать нет необходимости.
 
Добрый день, подскажите пожалуйста. Как сделать поиск то по определенному полю и вырезать все значение их него??
 
Назад
Сверху