我想只获取所有接收者ID匹配的记录,但查询中的find_in_set
或IN
运算符会返回包含任何ID的所有记录。
我希望只获得与我的数据库中所有all_recipients
列匹配的记录。
例如,我想在以下情况下只获取 pid = 6 的记录:
我有以下查询:
SELECT * FROM `conf_event_message_recipients` WHERE receiver IN (6622,6607) AND event_id = 46
和数据库记录:
pid mid seq receiver all_recipients event_id status
8 127 9 6622 6607,6622,6624 46 2
6 127 9 6622 6607,6622 46 2
9 127 9 6622 6607,6622,6624 46 2
我怎样才能做到这一点?
答案 0 :(得分:2)
它不漂亮,但是当您在列表中存储列表而不是使用关联/联结表时会发生这种情况。你真的应该修复数据结构。
以下方法通过对每个值使用find_in_set()
来计算字符串中的匹配数。然后将它与字符串中的项目数进行比较,使用技巧将每个逗号替换为两个字符,取长度,减去原始长度并添加一个:
SELECT *
FROM `conf_event_message_recipients`
WHERE (find_in_set(6622, all_recipients) > 0 +
find_in_set(6607, all_recipients) > 0
) = (length(replace(all_recipients, ',', ',,')) - length(all_recipients) + 1)
WHERE event_id = 46;
编辑:
还有另一种方法,也不漂亮:
select *
from conf_event_message_recipients
where replace(replace(replace(concat(',', all_recipients, ',', ',6622,', '',
) ',6607,', ''
), ',', ''
) = '' and
event_id = 46;
也就是说,用空字符串替换每个id,然后删除逗号并确保没有任何内容。额外的逗号是为了防止“660”在替换中匹配“6607”。
答案 1 :(得分:1)
使用正常的相等比较:
SELECT *
FROM conf_event_message_recipients
WHERE all_recipients = '6607,6622'
或者如果您不能保证订单:
SELECT *
FROM conf_event_message_recipients
WHERE CHAR_LENGTH(all_recipients) - CHAR_LENGTH(REPLACE(all_recipients, ',', '')) = 1
AND FIND_IN_SET('6607', all_recipients)
AND FIND_IN_SET('6622', all_recipients)
第一个条件计算字段中逗号的数量,该值比值的数量少一个。然后剩下的条件检查每个所需的值是否在字段中。
如果表很大,这是一个非常低效的查询。您需要规范化架构以解决此问题。
答案 2 :(得分:1)
您可以使用以下查询:
SELECT * FROM `conf_event_message_recipients` WHERE all_recipients LIKE '%6622%' AND all_recipients LIKE '%6607%' AND LENGTH(all_recipients) = 9 AND event_id = 46
根据LENGTH(all_recipients)
all_recipients
的值