MySQL动态HAVING子句

时间:2012-08-07 19:46:09

标签: mysql

我写了SELECT语句完美无缺。但是,我需要进行一些更改,以便它现在从表单中获取用户提交的信息,并根据该结果返回数据库中的结果。

它基本上是一个产品搜索 - 如果用户搜索“红色”,他们将获得所有红色的项目。如果他们搜索“红色”和“木头”,他们将只收回红色和木头制成的物品。

这是我的HAVING条款:

HAVING values LIKE "%Red%" AND values LIKE "%Wood%"

如果我有一系列5个下拉菜单,每个菜单都有不同的术语集,我应该根据用户使用的下拉菜单动态构建HAVING子句吗?怎么会这样做?

3 个答案:

答案 0 :(得分:1)

我会选择静态SQL语句,因为用户可以选择五个“选项”。

我要做的是使用一个空字符串作为对特定选项表示“无限制”的值,所以我的陈述将是这样的:例如

HAVING `values` LIKE CONCAT('%',:b1,'%')
   AND `values` LIKE CONCAT('%',:b2,'%')
   AND `values` LIKE CONCAT('%',:b3,'%')
   AND `values` LIKE CONCAT('%',:b4,'%')
   AND `values` LIKE CONCAT('%',:b5,'%')

仅对选项1和2应用限制,对选项3没有限制,例如

$sth->bind_param(':b1','Red');
$sth->bind_param(':b2','Wood');
$sth->bind_param(':b3','');
$sth->bind_param(':b4','');
$sth->bind_param(':b5','');

仅对选项2应用限制,例如

$sth->bind_param(':b1','');
$sth->bind_param(':b2','Wood');
$sth->bind_param(':b3','');
$sth->bind_param(':b4','');
$sth->bind_param(':b5','');

这允许您拥有静态语句,并且唯一需要更改的是为绑定参数提供的值。


也可以使用NULL值来表示选项的“无限制”,但是当提供NULL值时,您需要修改SQL语句以执行“无限制”。要么特别检查NULL值,例如

HAVING ( `values` LIKE CONCAT('%',:b1,'%') OR :b1 IS NULL )
   AND ( `values` LIKE CONCAT('%',:b2,'%') OR :b2 IS NULL )
   AND ( `values` LIKE CONCAT('%',:b3,'%') OR :b3 IS NULL )

- 或 - 只需将NULL转换为空字符串,以便在LIKE谓词中使用,例如

HAVING `values` LIKE CONCAT('%',IFNULL(:b1,''),'%')
   AND `values` LIKE CONCAT('%',IFNULL(:b2,''),'%')
   AND `values` LIKE CONCAT('%',IFNULL(:b3,''),'%')

同样的技术也适用于WHERE子句。您可能需要考虑WHERE子句是否更适合您的情况。 (我们无法从提供的信息中得知。)

但请注意,HAVING子句不限制语句中包含哪些行;相反,HAVING子句仅限制返回结果集中的哪些行。 HAVING子句几乎在执行计划中最后应用(我认为它仅遵循ORDER BY和LIMIT。

HAVING子句可以应用于聚合,WHERE子句不能这样做。 HAVING子句可以引用SELECT列表中的列,WHERE子句不能这样做。

(另请注意,VALUES是一个保留字,如果它不合格(前面有alias.,则可能需要用反引号括起来。)

答案 1 :(得分:0)

不,你不应该构建HAVING子句。

是的,您可以按照建议构建WHERE子句。

HAVING用于强制涉及群组聚合功能的条件。

答案 2 :(得分:0)

这种方法适用于涉及更多条件的地方,但您也可以在5上使用它们。将菜单值收集到临时表中,然后将它们连接到LIKE条件

上的查询
SELECT .... FROM MyTable
INNER JOIN  MyTempTable
ON values LIKE '%' + MenuValue '%'