【问题标题】:Filtering data with Select (advanced) [duplicate]使用 Select 过滤数据(高级)[重复]
【发布时间】:2018-10-14 06:07:18
【问题描述】:

我正在进行一个项目,我有 3 种可能的过滤器。按名称、城市和省份过滤。现在我正在做的是尝试考虑所有可能性的简单 IF。

示例:它可以是 [Name][City][All] 或 [All][City][province] 或 [All][All][province],总共有 8 到 9 种可能性。这意味着如果必须在我的 PHP 代码中执行大约 8 个条件来尝试捕获所有内容。

所以我的问题是:MySql 有没有办法执行 SELECT data1.. FROM tableName WHERE ... 但是当我不给出例如城市时,它只搜索名称和省份。

【问题讨论】:

标签: php html mysql filter


【解决方案1】:

有几种方法。一种方法是动态构建 SQL 文本。如果选项是离散的,我们可以单独处理每个条件,包括或不包括。作为模式的示例:

开始 SQL 文本:

  $sql = "SELECT ...
            FROM ... 
           WHERE 1=1 ";

有条件地附加搜索条件

  if(  we need to add a condition on city ) {
       $sql .= " AND t.city LIKE :city ";
  }
  if(  we need to add a condition on province ) {
       $sql .= " AND t.province LIKE :province ";
  }
  if(  we need to add a condition on name  ) {
       $sql .= " AND t.name LIKE :name ";
  }

完成 SQL 文本

  $sql .= " ORDER BY ..."; 

准备 SQL 文本(这里是 echo/var_dump/log $sql 的内容进行调试的好地方)

  $sth = $dbh->prepare($sql);

为我们添加的任何搜索条件有条件地绑定值

  if(  we need to add a condition on city ) {
      $sth->bindValue(':city',$city);
  }
  if(  we need to add a condition on province ) {
      $sth->bindValue(':province',$province);
  }
  if(  we need to add a condition on name  ) {
      $sth->bindValue(':name',$name);
  }

执行

  $sth->execute();

另一种选择是在 WHERE 子句中使用带有表达式的静态 SQL,使用“特殊”保留值来表示“不搜索”。

在本例中,我们使用长度为零的字符串表示“无搜索条件”...

  $sql = "SELECT ...
            FROM ... t
           WHERE ( :city1     = '' OR t.city     LIKE :city2     ) 
             AND ( :province1 = '' OR t.province LIKE :province2 )
             AND ( :name1     = '' OR t.name     LIKE :name2     )
           ORDER BY ...";

  $sth = $dbh->prepare($sql);

  $sth->bindValue(':city1'     , $city     ); 
  $sth->bindValue(':city2'     , $city     ); 
  $sth->bindValue(':province1' , $province ); 
  $sth->bindValue(':province2' , $province ); 
  $sth->bindValue(':name1'     , $name     ); 
  $sth->bindValue(':name2'     , $name     ); 

  $sth->execute();

【讨论】:

    【解决方案2】:

    这可以在 mysql 或 php 中完成 - 但恕我直言,php 解决方案看起来更干净。为此,您只需在运行时构建查询。

    $name = ...
    $city = ...
    $province = ...
    
    $fields = [
        'name' => $name,
        'city' => $city,
        'province' => $province
    ];
    $where = [];
    $values = [];
    
    foreach ($fields as $field => $value) {
        if ($value) {
            $where[] = "$field = :$field";
            $values[$field] = $value;
        }
    }
    
    $sql = 'SELECT * FROM table';
    if (count($where) > 0) {
        $sql .= ' WHERE ' . join(' AND ', $where);
    }
    
    // using pdo
    $query = $pdo->prepare($sql);
    $query->execute($values);
    // ...
    

    【讨论】:

      【解决方案3】:

      您可以这样做,将您的过滤器存储在一个数组中并检查每个过滤器是否存在。如果过滤器有值,则使用 where 语句数组将其动态添加到 where 子句中。

      $filters = ['name', 'city', 'province'];
      $where   = [];
      
      foreach($filters as $filter) {
        if(!empty($_POST[$filter])) {
          $param_name          = ":{$filter}";
          $where[]             = "{$filter} = {$param_name}";
          $params[$param_name] = $_POST[$filter];
        }
      }
      
      $where_str = !empty($where) ? 'WHERE ' . join(' AND ', $where) : '';
      
      $sql = "SELECT * FROM table {$where_str}";
      
      $db = new PDO(<connection_str>);
      
      $stmt = $db->prepare($sql);
      
      $results = $stmt->execute($params);
      

      【讨论】:

      • 如果没有发布过滤器怎么办?
      • @Philipp 我希望 OP 可以自己解决这个问题...... :) 但现在进行了编辑以包括没有提供过滤器的情况。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 2020-01-04
      • 1970-01-01
      相关资源
      最近更新 更多