简体   繁体   English

如何连接/构建可选查询? (PHP / MySQL)

[英]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 . 我的问题是在正确放置WHEREAND同时构建$allquery ,因为有时我什至不需要WHERE ,有时我只需要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) 还是其他方法更好(例如3个独立的查询并加入它们)

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. 我只是将所有参数传递给最终查询,但首先要检查它们是否为null。 For instance, if you have 3 filters like in your example, my where clause would be something like: 例如,如果您在示例中有3个过滤器,则我的where子句将类似于:

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: 这样,您具有3个主要优点:

  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. 1=1 ,并将AND放在每个过滤器之前。

$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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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