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

Тема в разделе "Базы данных", создана пользователем drkrol, 22 дек 2017.

Модераторы: latteo
  1. drkrol

    drkrol Постоялец

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

    PHP:
    $sql 'SELECT * FROM main WHERE nameclient LIKE :who AND (datestart BETWEEN :datestart AND :dateend) ';
    $pdo_statement->bindValue(':who',$namePDO::PARAM_STR);
    $pdo_statement->bindValue(':datestart',$dstartPDO::PARAM_STR);
    $pdo_statement->bindValue(':dateend',$dendPDO::PARAM_STR);
    $pdo_statement->execute();
    $result $pdo_statement->fetchAll();
    ?>
    переменные who, dstart и dend я получаю из формы.
    Проблема состоит в том, что какое-то из полей формы, будь это имя или диапазон дат, может быть не заполнено. Сейчас, в моём случае, если какое-то из полей не заполнить, то вернётся пустой результат.
    Подскажите, как сделать, чтобы sql игнорировал пустые поля?
     
  2. BaBL

    BaBL

    Регистр.:
    13 ноя 2012
    Сообщения:
    166
    Симпатии:
    106
    Надо переписать запрос, потому что в случае пустых полей, у тебя проблема будет не в значениях, а в самом запросе.

    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',$namePDO::PARAM_STR);
    $pdo_statement->bindValue(':datestart',$dstartPDO::PARAM_STR);
    $pdo_statement->bindValue(':dateend',$dendPDO::PARAM_STR);
    $pdo_statement->execute();
    $result $pdo_statement->fetchAll();
    ?>
     
    Цуиьфыеук и NickSan нравится это.
  3. drkrol

    drkrol Постоялец

    Регистр.:
    6 мар 2016
    Сообщения:
    107
    Симпатии:
    10
    костыль какой-то получается. У меня таких полей будет 20: и цена, и цвет, и кол-во. Разве нет в Php такой функции, чтобы без if всё нормально работало?
     
  4. BaBL

    BaBL

    Регистр.:
    13 ноя 2012
    Сообщения:
    166
    Симпатии:
    106
    Это не костыль, а нормальная реализация фильтра, подобного вашему. В PHP нету понятия какая пятка у вас сейчас чешется. Если вам нужно сделать РАЗНЫЕ запросы - то уж извините, PHP не может додумать за вас бизнес логику приложения.

    Используйте ORM, они эту реализацию спрячут в себе, но, грубо говоря, она будет подобна той что я указал. К примеру в AR в Yii2 есть метод ->addFilterWhere() который убирает это условие из построителя запроса, если в параметрах передан null / false.
     
  5. NickSan

    NickSan Постоялец

    Регистр.:
    23 авг 2012
    Сообщения:
    69
    Симпатии:
    38
    это не костыль, а правильное обращение к БД и в этом нет ничего страшного.
     
    BaBL нравится это.
  6. Nei

    Nei Nosce te ipsum

    Регистр.:
    5 сен 2009
    Сообщения:
    660
    Симпатии:
    519
    Эм, а привязывать значения разве не надо только в том случае, если они используются в запросе? о_О
    Т.е. по идее так как-то:

    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 по умолчанию используется, т.е. явно задавать нет необходимости.
     
  7. Dmytrodddddd

    Dmytrodddddd Создатель

    Регистр.:
    23 мар 2017
    Сообщения:
    27
    Симпатии:
    21
    Добрый день, подскажите пожалуйста. Как сделать поиск то по определенному полю и вырезать все значение их него??
     
  8. Midnayt

    Midnayt Писатель

    Регистр.:
    30 янв 2018
    Сообщения:
    2
    Симпатии:
    0
    Update table set column = "" where column like "%текст поиска%"