通过运行union和intersection来组合5个sql查询的结果

时间:2012-11-30 13:44:44

标签: php mysql sql union intersect

我有5个查询,如下所示,我需要在所有

上执行联合
  if($dv_state_ids!="")//check if no state is entered
    $state_sql="SELECT pkg_id FROM package_state where state_id in ($dv_state_ids)  ";
  if($dv_city_ids!="")//check if no city is entered
    $city_sql="SELECT pkg_id FROM package_city where  city_id in ($dv_city_ids)";
  if($dv_category_ids!="")//check if nocategory is entered
    $category_sql="SELECT pkg_id FROM package_category where category_id in ($dv_category_ids) ";
  if($dv_sub_category_ids!="")//check if no subcategory is found
    $sub_category_sql="SELECT pkg_id FROM package_category where subcategory_id in ($dv_sub_category_ids) ";
  if($dv_category_ids!="")
    $package_sql="SELECT pkg_id FROM package where id in ($dv_category_ids) ";

我可以通过以下语句对上述查询运行联合

$sql_get_any_packages=$state_sql." union ".$city_sql." 
union 
".$category_sql." union ".$sub_category_sql." union ".$package_sql ;

但是如果任何查询为null,那么这将在mysql中生成错误。 一种方法是我构成32个条件(由这5个查询形成以检查不同的条件)

任何身体都可以建议我另一条出路

我还需要对这5个查询的结果执行交集并且sql不支持INTERSECT

请帮我解决这个问题

1 个答案:

答案 0 :(得分:1)

“查询为空”表示PHP变量为null。这绝不是SQL或SQL联合所特有的。

重复if s

所以你能做的就是:

$sql_get_any_packages = "";
if (!is_null($state_sql))
 $sql_get_any_packages .= " union " . $state_sql;
if (!is_null($city_sql))
 $sql_get_any_packages .= " union " . $city_sql;
if (!is_null($category_sql))
 $sql_get_any_packages .= " union " . $category_sql;
if (!is_null($sub_category_sql))
 $sql_get_any_packages .= " union " . $sub_category_sql;
if (!is_null($package_sql))
 $sql_get_any_packages .= " union " . $package_sql;
$sql_get_any_packages = substr($sql_get_any_packages, strlen(" union "));

这只会收集所有非null部分,包括每个部分的前导" union ",并在结尾删除最初的" union "。如果所有查询可能同时为null,则最终结果为FALSE

使用数组

作为替代方案,您可以将部件放入数组中,使用array_filter删除null元素,然后implode使用" union "粘贴结果example on ideone。相应的代码可能如下所示(另请参阅use prepared statements):

$sql_get_any_packages = array(
    $state_sql,
    $city_sql,
    $category_sql,
    $sub_category_sql,
    $package_sql);
$sql_get_any_packages = array_filter($sql_get_any_packages);
$sql_get_any_packages = implode(" union ", $sql_get_any_packages);

关于交叉

如果你想交叉结果,你不想联合他们的联盟。一旦你进行了工会,你就无法再访问它的各个部分了,所以你无法将它们相互比较。要实现交叉,可以在SQL中使用 join 。完整的示例可能如下所示:

SELECT package_state.pkg_id
FROM package_state, package_city, package_category, package_category, package
WHERE package_state.state_id IN ($dv_state_ids)
  AND package_city.city_id IN ($dv_city_ids)
  AND package_category.category_id IN ($dv_category_ids)
  AND package_category.subcategory_id IN ($dv_sub_category_ids)
  AND package.id in ($dv_category_ids)
  AND package_state.pkg_id == package_city.pkg_id
  AND package_state.pkg_id == package_category.pkg_id
  AND package_state.pkg_id == package.pkg_id

您可以使用我上面描述的解决方案来构建这样的查询,但它们会变得稍微复杂一些。特别是,上述查询中的表package_state与所有其他表的作用略有不同:这是您SELECT输出值的表格形式,s also the table which occurs on the left hand side of all the pkg_id {{ 1}} foo IN(bar)`条件。然后,您可以使用表名数组的第一个元素来扮演特殊角色。

注意SQL注入

小心将字符串从用户请求粘贴到查询中。它们可能包含丑陋的东西,会破坏您的数据。确保输入是正确的,例如通过检查它只是一个以逗号分隔的整数值列表。或{{3}},它可以将您与大多数问题隔离开来。