带有多个过滤器的mySQL搜索语句

时间:2012-03-10 15:41:12

标签: php mysql search checkbox

我一直试图解决这个问题几天,但一直未能找到解决方案。很可能是因为我认为我没有问正确的问题。

这是......

我正在尝试在我的网站上创建一份律师名单。

Table 1
ID (primary)
Name
Category1 (fkey)
Category2 (fkey) 
Category3 (fkey)
Category4 (fkey)
Category5 (fkey)
Location1 (fkey)
Location2 (fkey)
Location3 (fkey)
Location4 (fkey)
Location5 (fkey)

Table 2 - Locations
ID (primary)
Name 

Table 3 - Categories
ID (primary)
Name

因此律师有多个类别和多个地点 - >与表2和表3的一对多关系

第一个问题:我是否正确设置了表1?我是否需要有多个位置和类别列(即location1,location2,location3等等)或者我是否使这一点变得复杂?

下一步...

我想在我的网站上进行复选框样式搜索。用户可以按位置和/或按类别进行搜索。使用复选框,他们可以选择多个位置和/或类别。复选框值是位置和类别(不是名称)的ID

因此可以采取三种方式。

  1. 仅按地点搜索
  2. 仅按类别搜索
  3. 按地区内的类别搜索
  4. 我有两个问题。

    1. 我可以获得方案1& 2工作,但只有选中一个复选框。
    2. 我不知道如何开始让方案3工作。
    3. 以下是我对场景1& 2

      $AttorneyLocation = $_POST['AttorneyLocation'];
      
      for ($i="0"; $i<count($AttorneyLocation); $i++) {
          if (!is_numeric($AttorneyLocation[$i])) {
              $AttorneyLocation[$i]="";
          }
          if (empty($AttorneyLocation[$i])) {
              unset($AttorneyLocation[$i]);
          }
      }
      
      $AttorneyLocation = implode (" OR ", $AttorneyLocation);
      
      $sqlCommand = "SELECT att_id, att_name, att_logo, att_addy, att_town, att_profile_url FROM attorneys WHERE att_location1='$AttorneyLocation' OR att_location2='$AttorneyLocation' OR att_location3='$AttorneyLocation' OR att_location4='$AttorneyLocation' OR att_location5='$AttorneyLocation'";
      

      同样,这有效,但只有当选中一个复选框时,如果选择了两个或更多,它将失败。基本上它似乎只搜索已选中的最后一个复选框,忽略它之前的复选框。

      对于方案3 - 我再次确定从哪里开始,如何在位置搜索中将类别搜索结合在一起?

      如果有人可以指出我的方向很好,非常感谢!这是我第一次尝试创建这样的东西!

      如果需要,这是我的表单代码 - 全部动态创建

       <input type='checkbox' name='AttorneyCategory[]' value='$cat_id'> $category<br />
       <input type='checkbox' name='AttorneyLocation[]' value='$loc_id'> $location<br />
      

3 个答案:

答案 0 :(得分:4)

正如@JonathanLeffler所指出的,表1的结构是不做的完美例子。您的类别*和位置*字段应从表1中删除,并替换为两个多对多表 - attorney_locations(attorney_id,location_id)和attorney_categories(attorney_id,category_id)。

首先修改您的数据库结构,然后我们可以解决其他问题。

下一轮 -

<?php

foreach ($_POST['AttorneyLocation'] AS $key => $val)    {
    if (is_numeric($val)) {
        $_POST['AttorneyLocation'][$key] = intval($val);
    } else {
        unset($_POST['AttorneyLocation'][$key]);
    }
}

$AttorneyLocations = implode (',', $_POST['AttorneyLocation']);

foreach ($_POST['AttorneyCategory'] AS $key => $val)    {
    if (is_numeric($val)) {
        $_POST['AttorneyCategory'][$key] = intval($val);
    } else {
        unset($_POST['AttorneyCategory'][$key]);
    }
}

$AttorneyCategories = implode (',', $_POST['AttorneyCategory']);

$sqlCommand = 'SELECT DISTINCT att_id, att_name, att_logo, att_addy, att_town, att_profile_url FROM attorneys ';

if ($AttorneyLocations) {
    $sqlCommand .= 'INNER JOIN attorney_locations ON attorneys.att_id = attorney_locations.attorney_id ';
}
if ($AttorneyCategories) {
    $sqlCommand .= 'INNER JOIN attorney_categories ON attorneys.att_id = attorney_categories.attorney_id ';
}

$sqlCommand .= 'WHERE 1=1 ';

if ($AttorneyLocations) {
    $sqlCommand .= "AND attorney_locations.location_id IN ($AttorneyLocations) ";
}
if ($AttorneyCategories) {
    $sqlCommand .= "AND attorney_categories.category_id IN ($AttorneyCategories)";
}

答案 1 :(得分:2)

您应该打印出来自implode()

的内容
$AttorneyLocation = implode (" OR ", $AttorneyLocation);

它不是有效的SQL语法,因为您需要它来读取类似的内容:

location = 'location1' OR location = 'location2' OR ...

因此,您没有生成有效的SQL,因为您肯定会看到是否打印了SQL。

您的Table1是一场关系灾难。 CategoryNLocationN列是SQL'代码味道'。目前尚不清楚该表的含义;是记录类别和位置之间的“AND”或“OR”连接,是仅与Location5关联的Category5还是与Location1相关?在不知道数据意味着什么的情况下,我们无法可靠地提供 正确的设计。


鉴于每位律师最多可以执行5类法律,并且可以在最多5个地方执业,那么表格的更好设计可能是:

Attorney
ID           (pkey)
Name
...other details...

AttorneyCategory
AttorneyID   (fkey - references Attorney)
Category     (fkey - references Category)
(AttorneyID, Category) (pkey)

AttorneyLocation 
AttorneyID   (fkey - references Attorney)
Location     (fkey - references Location)
(AttorneyID, Category) (pkey)

这实际上也更容易查询,因为您不必在五个不同列中的每一列中查找相同的位置名称,也不必在五个不同的列中查找相同的类别。

答案 2 :(得分:-1)

好吧,既然你使用的是PHP我只是建议你为你想要的每个过滤器做一个IF语句,或许可以让一些过滤器一起工作2或3个过滤器。你的数据库设置正确,只需创建PHP,如果有不同的查询,它应该工作。