Php 如何对SQL中包含多个值的数据库列执行WHERE NOT IN
当数据库列和检查条件中有多个值时,如何执行WHERE NOT IN条件 如果用户不属于excludedUserGroup,我想将其状态设置为1 用户状态表:-用户状态Php 如何对SQL中包含多个值的数据库列执行WHERE NOT IN,php,mysql,sql,Php,Mysql,Sql,当数据库列和检查条件中有多个值时,如何执行WHERE NOT IN条件 如果用户不属于excludedUserGroup,我想将其状态设置为1 用户状态表:-用户状态 +---------+--------+ | user_id | status | +=========+========+ | 1 | 1 | +---------+--------+ 用户表:-用户 +---------+---------------+---------------------+ |
+---------+--------+
| user_id | status |
+=========+========+
| 1 | 1 |
+---------+--------+
用户表:-用户
+---------+---------------+---------------------+
| user_id | user_group_id | secondary_group_ids |
+=========+===============+=====================+
| 1 | 4 | 2,8,9 |
+---------+---------------+---------------------+
变量:-
$excludeUsergroups = "8,7,12"
$finalExcludeUsergroups = implode(",", $excludeUsergroups);
我要执行的查询是:-
更新用户\u状态
在us上左加入用户u.user=u.user
设置us.status=1
其中(u.user\u group\u id不在(“.finalExcludeUsergroups.”)中,u.secondary\u group\u id不在(“.finalExcludeUsergroups.”)中)
现在的问题是,u.secondary\u group\u id和$finalExcludedUsergroups都有多个值,它在检查第二个不在时给出错误。
它只包含1个值,因此会检查用户\u组\u id,但当它转到辅助\u组\u id时会失败
如何执行第二个NOT IN,它将检查辅助组ID的每个值,并使用$FinalExcludeUserGroups进行检查
更新
我使用FIND_IN_SET进行了测试,但是它不起作用,因为FIND_IN_SET检查字符串列表中的字符串FIND_IN_SET(字符串,字符串列表)
但是在我的例子中,我想检查字符串列表中的字符串列表,这在查找列表中是不可能的。我对您的问题很感兴趣,想知道一个简单的用户定义函数是否有帮助,所以准备下面的示例。如果在数据库中创建函数,则应该能够在查询中向其传递两个“逗号分隔值”字符串,以查看是否共享了任何组。正如您所注意到的,我将其命名为否定格(即不相交),因为我无法很快想出一个合适的短名称来表示肯定格(即集合\u有\u一个\u或\u多个\u元素\u共同点似乎有点长!) 希望有人在某个时候会发现这很有用
/*
MySQL Function to determine whether two comma-separated strings
supplied as parameters share any common elements.
Example Usage:
SELECT SETS_ARE_DISJOINT('8,7,12', '2,8,9'); --> False - shared entry = 8
SELECT SETS_ARE_DISJOINT('7,12', '2,8,9'); --> True - no shared entries
*/
CREATE FUNCTION SETS_ARE_DISJOINT(csv1 TEXT, csv2 TEXT)
RETURNS BOOLEAN
LANGUAGE SQL
BEGIN
DECLARE Occurrences INT;
DECLARE myValue TEXT;
SET Occurrences = LENGTH(TRIM(csv1)) - LENGTH(REPLACE(TRIM(csv1), ',', ''));
Loop1:
WHILE Occurrences > 0 DO
SET myValue = SUBSTRING_INDEX(csv1, ',', 1);
IF (myValue != '') THEN
IF FIND_IN_SET(myValue , csv2) > 0 THEN
RETURN FALSE;
END IF;
ELSE
LEAVE Loop1;
END IF;
SET Occurrences = LENGTH(TRIM(csv1)) - LENGTH(REPLACE(TRIM(csv1), ',', ''));
IF (Occurrences = 0) THEN
LEAVE Loop1;
END IF;
SET csv1 = SUBSTRING(csv1, LENGTH(SUBSTRING_INDEX(csv1, ',', 1)) + 2);
END WHILE;
RETURN TRUE;
END;
我对你的问题很感兴趣,想知道一个简单的用户定义函数是否有帮助,所以准备了下面的示例。如果在数据库中创建函数,则应该能够在查询中向其传递两个“逗号分隔值”字符串,以查看是否共享了任何组。正如您所注意到的,我将其命名为否定格(即不相交),因为我无法很快想出一个合适的短名称来表示肯定格(即集合\u有\u一个\u或\u多个\u元素\u共同点似乎有点长!) 希望有人在某个时候会发现这很有用
/*
MySQL Function to determine whether two comma-separated strings
supplied as parameters share any common elements.
Example Usage:
SELECT SETS_ARE_DISJOINT('8,7,12', '2,8,9'); --> False - shared entry = 8
SELECT SETS_ARE_DISJOINT('7,12', '2,8,9'); --> True - no shared entries
*/
CREATE FUNCTION SETS_ARE_DISJOINT(csv1 TEXT, csv2 TEXT)
RETURNS BOOLEAN
LANGUAGE SQL
BEGIN
DECLARE Occurrences INT;
DECLARE myValue TEXT;
SET Occurrences = LENGTH(TRIM(csv1)) - LENGTH(REPLACE(TRIM(csv1), ',', ''));
Loop1:
WHILE Occurrences > 0 DO
SET myValue = SUBSTRING_INDEX(csv1, ',', 1);
IF (myValue != '') THEN
IF FIND_IN_SET(myValue , csv2) > 0 THEN
RETURN FALSE;
END IF;
ELSE
LEAVE Loop1;
END IF;
SET Occurrences = LENGTH(TRIM(csv1)) - LENGTH(REPLACE(TRIM(csv1), ',', ''));
IF (Occurrences = 0) THEN
LEAVE Loop1;
END IF;
SET csv1 = SUBSTRING(csv1, LENGTH(SUBSTRING_INDEX(csv1, ',', 1)) + 2);
END WHILE;
RETURN TRUE;
END;
我会使用MySql
而不是REGEXP
和正则表达式/(^ | \,)3($| \,)/
将:id
参数设置为$finalExcludeUsergroups
,
我会举一个例子说明如何使用,但不知道您是否在使用mysqli、pdo、框架等等
正则表达式的分解:
- 组
将匹配字符串的开头或逗号(^ |\,)
将匹配您要查找的id(对于代码,我将在此处使用参数)3
- 组
将匹配字符串或逗号的结尾($\124;\,)
而不是REGEXP
和正则表达式/(^ | \,)3($| \,)/
将:id
参数设置为$finalExcludeUsergroups
,
我会举一个例子说明如何使用,但不知道您是否在使用mysqli、pdo、框架等等
正则表达式的分解:
- 组
将匹配字符串的开头或逗号(^ |\,)
将匹配您要查找的id(对于代码,我将在此处使用参数)3
- 组
将匹配字符串或逗号的结尾($\124;\,)
foreach ($excludeUsergroups as $usergroup)
{
$statusJoiner[] = 'FIND_IN_SET(' . $db->quote($usergroup) .' , user.secondary_group_ids) = 0';
}
然后我加入了他们的行列
if (!empty($statusJoiner))
{
//Joiner for hit part
$Joiner = ' AND ';
$statusFinalJoiner = implode($Joiner,$statusJoiner);
}
然后查询如下所示:-
Update user_status us
LEFT JOIN user u ON us.user = u.user
SET us.status = 1
WHERE (u.user_group_id NOT IN (". $finalExcludeUsergroups . ") AND " . $statusFinalJoiner . ")
就是这样,结果是:)好的,所以我通过foreach循环实现了我想要做的事情,我循环了$finalExcludeUsergroups,创建了FIND_IN_集合的数组,然后将其包含在查询中
foreach ($excludeUsergroups as $usergroup)
{
$statusJoiner[] = 'FIND_IN_SET(' . $db->quote($usergroup) .' , user.secondary_group_ids) = 0';
}
然后我加入了他们的行列
if (!empty($statusJoiner))
{
//Joiner for hit part
$Joiner = ' AND ';
$statusFinalJoiner = implode($Joiner,$statusJoiner);
}
然后查询如下所示:-
Update user_status us
LEFT JOIN user u ON us.user = u.user
SET us.status = 1
WHERE (u.user_group_id NOT IN (". $finalExcludeUsergroups . ") AND " . $statusFinalJoiner . ")
就是这样,结果是:)我建议规范化您的数据模型。辅助组中的每个值都应存储在单独的表中的单独行中。然后,问题变得更容易解决。这就是为什么我们使用“数据库规范化”:是的,但是我不能这样做。在这种情况下,我使用的框架遵循这种结构,使用
FIND\u in\u SET
作为第二个子句。我假设数据是用逗号分隔的?@floGalen我在不同的答案中找到了FIND_IN_SET方法,但不明白它在这种情况下是如何工作的。我以前从未使用过它,查看过mysql文档,但不理解它。我建议您规范化数据模型。辅助组中的每个值都应存储在单独的表中的单独行中。然后,问题变得更容易解决。这就是为什么我们使用“数据库规范化”:是的,但是我不能这样做。在这种情况下,我使用的框架遵循这种结构,使用FIND\u in\u SET
作为第二个子句。我假设数据是用逗号分隔的?@floGalen我在不同的答案中找到了FIND_IN_SET方法,但不明白它在这种情况下是如何工作的。我以前从未使用过它,查看过mysql文档,但不理解它。那么你是说如果我有一个字符串'8,9,14',并且我使用正则表达式将:id替换为(比如)'9,11,20,22',结果将为“false”(因为两个字符串中都存在9),而如果我将:id替换为'10,11,12,20',结果将为“true”(没有共同的数字)?我想