简体   繁体   中英

How to concatenate / build optional queries? (PHP/MySQL)

I am building a filter functionality and am wondering how to best combine the optional queries together. For example:

$basicquery = "SELECT * FROM products";

$filter1 = mysqli_real_escape_string($connection, $_GET['filter1']);
// has_presence is my function that returns false if value is NULL or ""
$optional1 = (has_presence($filter1)) ? "feature1='{$filter1}'" : "";
$filter2 = mysqli_real_escape_string($connection, $_GET['filter2']);
$optional2 = (has_presence($filter2)) ? "feature2='{$filter2}'" : "";
$filter3 = mysqli_real_escape_string($connection, $_GET['filter3']);
$optional3 = (has_presence($filter3)) ? "feature2='{$filter3}'" : "";

// How to build this one correctly?
$allqueries = $basicquery . 
              " WHERE " .
              $optional1 . 
              " AND " . $optional2 . 
              " AND " . $optional3;

My problem is building the $allquery while placing the WHERE and AND correctly, because sometimes I don't even need the WHERE , and sometimes I just need 1 AND .

Is this the correct way to build such a query? (eg when condition is not specified, return all for this column). Or is a different approach better (eg 3 separate queries and join them)

One of my favourite approach to this problem is to use "null" values. I simply pass all of the parameters to the final query, but checking if they're null, first. For instance, if you have 3 filters like in your example, my where clause would be something like:

where (filter1 is null or column1 = filter1)
and (filter2 is null or column2 = filter2)
and (filter3 is null or column3 = filter3)

This way you have 3 main advantages:

  1. You can add as filters as you wish, and you don't have to worry about their permutations
  2. The performances are not impacted since if one of the filters is null, the check takes no time to execute
  3. If the database caches the query, you won't lose this advantage, because the query is always the same, you don't rebuild it every time as a concatenation of strings.
$query = "SELECT * FROM products";

$filter1 = mysqli_real_escape_string($connection, $_GET['filter1']);
$filter2 = mysqli_real_escape_string($connection, $_GET['filter2']);
$filter3 = mysqli_real_escape_string($connection, $_GET['filter3']);
if(has_presence($filter1) || has_presence($filter2) || has_presence($filter3) {
    $query .= " WHERE";
    $query .= (has_presence($filter1)) ? " feature1='{$filter1}'" : "";
    $query .= (has_presence($filter2)) ? " AND feature2='{$filter2}'" : "";
    $query .= (has_presence($filter3)) ? " AND feature2='{$filter3}'" : "";
}

Add 1=1 and put the AND before each filter.

$basicquery = "SELECT * FROM products";

$filter1 = mysqli_real_escape_string($connection, $_GET['filter1']);
// has_presence is my function that returns false if value is NULL or ""
$optional1 = (has_presence($filter1)) ? " AND feature1='{$filter1}'" : "";
$filter2 = mysqli_real_escape_string($connection, $_GET['filter2']);
$optional2 = (has_presence($filter2)) ? " AND feature2='{$filter2}'" : "";
$filter3 = mysqli_real_escape_string($connection, $_GET['filter3']);
$optional3 = (has_presence($filter3)) ? " AND feature2='{$filter3}'" : "";

// How to build this one correctly?
$allqueries = $basicquery . 
              " WHERE 1=1 " .
              $optional1 . 
              $optional2 . 
              $optional3;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM