Как создать SQL-запрос, который исключает строки без всех параметров

#php #mysql #sql #php-mysqlidb

#php #mysql #sql #php-mysqlidb

Вопрос:

У меня есть окно поиска, которое я предоставляю пользователю для ввода ключевых слов, которые они хотят найти. При отправке я разделяю слова в поле ввода (если их несколько) на массив и выполняю запрос для каждого отдельного слова. С помощью SQL я могу получать результаты, которые имеют хотя бы одно из значений, проблема в том, что я хочу получать только строки, которые имеют по крайней мере все параметры в том или ином столбце.

 public function employeeSearchAction()
    {
        if ($this->user_permissions < 1) {
            return 0;
        }
        // split search string into array based on spaces
        if ($this->data != '') {
            $searchParams = explode(' ', trim($this->data));
            // get any rows with any one of these values in them
            foreach ($searchParams as $s) {
                $this->db->orWhere('user_firstname', '%'.$s.'%', 'like');
                $this->db->orWhere('user_lastname', '%'.$s.'%', 'like');
                $this->db->orWhere('user_email1', '%'.$s.'%', 'like');
                $this->db->orWhere('user_phn_1', '%'.$s.'%', 'like');
                $this->db->orWhere('user_phn_2', '%'.$s.'%', 'like');
                $this->db->orWhere('user_phn_3', '%'.$s.'%', 'like');
                // $this->db->orWhere('user_address1', '%'.$s.'%', 'like');
                $this->db->orWhere('user_position', '%'.$s.'%', 'like');
                $this->db->orWhere('user_type', '%'.$s.'%', 'like');
                $this->db->orWhere('user_division', '%'.$s.'%', 'like');
                // $this->db->orWhere('user_position', $s);
                // $this->db->orWhere('user_type', $s);
                // $this->db->orWhere('user_division', $s);
            }
            $this->db->having('owner_id', $this->owner_id);
            $binaryArray = array_fill(0, sizeof($searchParams), 0);
            $results = $this->db->get('tblusers');
            $filtered = [];
            // filter rows to ensure that all rows have every parameter
            foreach ($results as $r) {
                $binaryArray = array_fill(0, sizeof($searchParams), 0);
                foreach ($binaryArray as $key=>$b) {
                    if (strpos(strtolower($r['user_firstname']), strtolower($searchParams[$key])) !== false ||
                  strpos(strtolower($r['user_lastname']), strtolower($searchParams[$key])) !== false ||
                  strpos($r['user_email1'], strtolower($searchParams[$key])) !== false ||
                  strpos($r['user_phn_1'], strtolower($searchParams[$key])) !== false ||
                  strpos($r['user_phn_2'], strtolower($searchParams[$key])) !== false ||
                  strpos($r['user_phn_3'], strtolower($searchParams[$key])) !== false ||
                  strpos(strtolower($r['user_position']), strtolower($searchParams[$key])) !== false ||
                  strpos(strtolower($r['user_type']), strtolower($searchParams[$key])) !== false ||
                  strpos(strtolower($r['user_division']), strtolower($searchParams[$key])) !== false
                  // strpos($r['user_address1'], strtolower($searchParams[$key])) !== false
                ) {
                        $binaryArray[$key] = 1;
                    }
                }
                if (!in_array(0, $binaryArray)) {
                    $filtered[] = $r;
                }
            }
        } else {
            $this->db->where('owner_id', $this->owner_id);
            $filtered = $this->db->get('tblusers');
        }
        foreach ($filtered as $r) {
            $user_phn_1 = $r['user_phn_1'] == '' ? 'N/A' : '<a href="tel: 1'.$r['user_phn_1'].'">'.preg_replace("/[^0-9]/", "", $r['user_phn_1']).'</a>';
            $user_phn_2 = $r['user_phn_2'] == '' ? 'N/A' : '<a href="tel: 1'.$r['user_phn_2'].'">'.$r['user_phn_2'].'</a>';
            $user_position = $r['user_position'] == '' ? 'N/A' : $r['user_position'];
            $user_type = $r['user_type'] == '' ? 'N/A' : $r['user_type'];
            $user_division = $r['user_division'] == '' ? 'N/A' : $r['user_division'];
            $user_email1 = $r['user_email1'] == '' ? 'N/A' : '<a href="mailto:'.$r['user_email1'].'">'.$r['user_email1'].'</a>';
            $user_address1 = $r['user_address1'] == '' ? 'N/A' : '<a href="https://maps.google.com/maps?q='.$r['user_address1'].'">'.$r['user_address1'].'</a>';
            $user_firstname = $r['user_firstname'] == '' ? 'N/A' : $r['user_firstname'];
            $user_lastname = $r['user_lastname'] == '' ? 'N/A' : $r['user_lastname'];
            $r['is_ready'] != 1 ? $user_firstname .=  ' <i title="Employee is not ready to work." class="orange fas fa-exclamation-triangle"></i>' : '';
            echo "
            <div class='search-form_row-container'>
              <div class='col-xs-6 col-sm-6'>
                 <i class='fas fa-file-signature'>
                 <span class='results-text results-text--name'>$user_lastname $user_firstname</span>
                 </i>
              </div>
              <div class='col-xs-6 col-sm-6'>
               <i class='fas fa-phone'>
                <span class='results-text results-text--phone'>{$user_phn_1}</span>
               </i>
              </div>
              <div class='col-xs-6 col-sm-6'>
                <a href='/includes/sql/store/users/curr_user.php?id={$r['user_id']}amp;goto=/users/user_profile_main.php'>
                 <i class='fas fa-link'>
                 <span class='results-text results-text--edit'>View Profile</span>
                 </i>
                </a>
              </div>
              <div class='col-xs-6 col-sm-6'>
                 <i class='fas fa-suitcase-rolling'>
                 <span class='results-text results-text--position'>$user_position</span>
                 </i>
              </div>
              <div class='col-xs-6 col-sm-6'>
                 <i class='fas fa-map-marker-alt'>
                 <span class='results-text results-text--type'>$user_type</span>
                 </i>
              </div>
              <div class='col-xs-6 col-sm-6'>
                 <i class='fas fa-i-cursor'></i>
                 <span class='results-text results-text--division'>$user_division</span>
                 </i>
              </div>
          </div>
        ";
        }
    }
 

То, что у меня есть, функционирует так, как должно, но я не могу не заметить, насколько это невероятно уродливо и неэффективно. Глядя на код, вы поймете, что я не использую необработанные запросы, я использую https://github.com/ThingEngineer/PHP-MySQLi-Database-Class Mysqlidb. Если вы хотите отказаться от формулировки своего ответа в этом формате, это нормально, эта библиотека может использовать необработанные запросы. Любая помощь приветствуется. Я просто предпочел бы извлекать только записи, содержащие все параметры, вместо записей, содержащих хотя бы один, а затем фильтровать их с помощью PHP.

Редактировать: мое намерение состоит в том, чтобы иметь возможность просто использовать этот SQL

Ответ №1:

Вам нужно запустить запрос, который извлекает данные для всех пользователей. Для каждого пользователя вам нужно проверить, содержат ли данные этого пользователя каждое ключевое слово. Если данные пользователя содержат все ключевые слова, то пользователь может быть включен в результаты поиска.

Итак, вам нужно иметь вложенные циклы. Внешний цикл проверяет каждого пользователя. Внутренний цикл проверяет каждое ключевое слово в пользовательских данных. Если данные пользователя содержат все ключевые слова, включите пользователя в результаты поиска. Если одно из ключевых слов отсутствует в пользовательских данных, прервите внутренний цикл и проверьте следующего пользователя.