这个问题是基于MYSQL join results set wiped results during IN () in where clause?的。
简单来说,如何将GROUP_CONCAT返回的字符串转换成逗号分隔的表达式列表,使IN()将其作为多个项的列表来循环处理?
N.B. MySQL文档似乎将IN()使用的“(逗号, 分隔的, 列表)”称为“表达式列表”,有趣的是,MySQL文档中几乎只有关于IN()的页面才涉及到表达式列表。因此,我不确定用于制作数组或临时表的函数是否在这里有用。
问题示例:从像这样的2个表的数据库中:
SELECT id, name, GROUP_CONCAT(tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id GROUP BY person.id;
+----+------+----------------------+
| id | name | GROUP_CONCAT(tag_id) |
+----+------+----------------------+
| 1 | Bob | 1,2 |
| 2 | Jill | 2,3 |
+----+------+----------------------+
我该如何将这个表达式转化为逻辑等价于 (1=X) AND (2=X) 的形式,因为它使用了字符串。
SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id
GROUP BY person.id HAVING ( ( 1 IN (GROUP_CONCAT(tag.tag_id) ) ) AND ( 2 IN (GROUP_CONCAT(tag.tag_id) ) ) );
Empty set (0.01 sec)
将GROUP_CONCAT结果视为列表进行处理,这样对于Bob来说,它就相当于:
SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 1
GROUP BY person.id HAVING ( ( 1 IN (1,2) ) AND ( 2 IN (1,2) ) );
+------+--------------------------+
| name | GROUP_CONCAT(tag.tag_id) |
+------+--------------------------+
| Bob | 1,2 |
+------+--------------------------+
1 row in set (0.00 sec)
...对于Jill来说,它等价于:
SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 2
GROUP BY person.id HAVING ( ( 1 IN (2,3) ) AND ( 2 IN (2,3) ) );
Empty set (0.00 sec)
那么总体结果将是一个排除搜索条款,要求所有列出的标签都不使用HAVING COUNT(DISTINCT...)吗?
(注意:此逻辑在没有AND的情况下也适用于字符串的第一个字符。例如:
SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id
GROUP BY person.id HAVING ( ( 2 IN (GROUP_CONCAT(tag.tag_id) ) ) );
+------+--------------------------+
| name | GROUP_CONCAT(tag.tag_id) |
+------+--------------------------+
| Jill | 2,3 |
+------+--------------------------+
1 row in set (0.00 sec)
FIND_IN_SET()
中,您不需要执行GROUP_CONCAT()
。您只需选择SELECT GROUP_CONCAT(tag.tag_id) AS tags_list
,然后使用HAVING FIND_IN_SET(20, tags_list)
即可。 - Treffynnon