转文: https://blog.csdn.net/weixin_47324958/article/details/128405165
在工作中,经常会遇到一对多的关系,比如用户和职务。想要在mysql中保存这种关系,一般有两种方式 一种是建立一张用户职务表,这样一条user_id就会存在多条记录。或者采用第二种方式,直接在用户表中增加一个职务字段,将职务拼接成用逗号分隔的字符串保存起来
问题来了,如果采用第二种方式的话,查询的时候要如何处理呢?下面介绍几种常见的处理方式

image.png
1. like
# 根据字符串包含模糊匹配查询
select * from data where gameIds like '%155%'
这种方式是否可行呢? 行,不能绝对的说有实用场景
- 如果只查询一种类型字段并且保证里面不能有相同的模糊匹配,如只查询gameIds是否包含155一种查询,并且保证里面没有其他不需要的155进行干扰
2. FIND_IN_SET
为了解决like存在的问题,还可以使用mysql提供的find_in_set(str, strlist)
select * from data where FIND_IN_SET('155', gameIds)
这样mysql就会把字段的值,按照逗号分隔的一个个元素去匹配,解决了like查询中存在模糊匹配干扰的问题
但是还是无法解决匹配多个值查询问题
3. REGEXP
regexp是mysql提供的强大的正则匹配方式。当需要匹配多个值的时候可以,sql如下:
select * from data where CONCAT (',',gameIds,',') REGEXP ',(155|10),'
这样就会查询gameIds,中包含了155和10的数据
结果如下:

image.png
gameIds中包含10,155的都会被查询出来,而且不受模糊匹配查询的干扰
4. go使用gorm框架使用方式
func (r *GroupRepository) FindGroupInstallInfo(platformId int, gameIdsAll []string) ([]model.GroupData, error) {
groupInstallInfoModel := make([]model.GroupData, 0, len(gameIdsAll))
gameIdsAllJoin := strings.Join(gameIdsAll, "|")
/*两种实现方式都可以*/
// "CONCAT (',',gameIds,',') REGEXP ? AND platformId=?", ",(101|20|1|30),",9
// "CONCAT (',',gameIds,',') REGEXP ',(101|20|30|11|1),' AND platformId=?", platformId,
querySql := fmt.Sprintf("CONCAT (',',gameIds,',') REGEXP ',(%s),' AND platformId=?", gameIdsAllJoin)
return groupInstallInfoModel, r.Db.Model(model.GroupData{}).Preload("GroupExtend").Where(
querySql, platformId,
).Find(&groupInstallInfoModel).Error
}