当前位置:网站首页>mysql字段userid逗号分开保存按userid查询
mysql字段userid逗号分开保存按userid查询
2022-07-03 04:05:00 【ITKEY_】
我的sql水平一般,仅是一个笔记。无法保存是最优解。仅供参考。
场景
有一张消息表,其中有一个收信人字段中把多个用户以,
分隔保存信息。我需要根据userid来查询信息。为了方便理解,我减化一下表结构。我的表结构如下:
message_id | receiver | sender | message | create_time |
---|---|---|---|---|
1 | user1,user2 | system | hello | 2022-06-30 16:30:12 |
2 | user1,user3 | system | world | 2022-06-30 16:31:19 |
3 | user3,user4,user5 | user1 | java | 2022-06-30 16:31:22 |
4 | user7,user8 | user2 | neovim | 2022-06-30 16:31:53 |
5 | itkey,lxyoucan | system | itkey | 2022-06-30 16:32:17 |
6 | user,user11 | good | very | 2022-06-30 16:38:18 |
表结构
create table t_message
(
message_id bigint auto_increment comment '消息ID'
primary key,
receiver varchar(4000) null comment '收件人',
sender varchar(200) not null comment '发件人',
message varchar(4000) not null comment '消息内容',
create_time datetime null comment '创建时间'
)
comment '消息中心';
数据
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (1, 'user1,user2', 'system', 'hello', '2022-06-30 16:30:12');
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (2, 'user1,user3', 'system', 'world', '2022-06-30 16:31:19');
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (3, 'user3,user4,user5', 'user1', 'java', '2022-06-30 16:31:22');
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (4, 'user7,user8', 'user2', 'neovim', '2022-06-30 16:31:53');
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (5, 'itkey,lxyoucan', 'system', 'itkey', '2022-06-30 16:32:17');
INSERT INTO t_message (message_id, receiver, sender, message, create_time) VALUES (6, 'user,user11', 'good', 'very', '2022-06-30 16:38:18');
实践
[错误的示范]like模糊匹配
首先我第一个思路想到的是使用like语句进行模糊查询。看似简单易用,但是会有bug。
比如查询user3
:
select * from t_message where receiver like '%user3%';
message_id | receiver | sender | message | create_time |
---|---|---|---|---|
2 | user1,user3 | system | world | 2022-06-30 16:31:19 |
3 | user3,user4,user5 | user1 | java | 2022-06-30 16:31:22 |
没有任何问题,但如果我要查询user
用户的数据呢?
select * from t_message where receiver like '%user%';
message_id | receiver | sender | message | create_time |
---|---|---|---|---|
1 | user1,user2 | system | hello | 2022-06-30 16:30:12 |
2 | user1,user3 | system | world | 2022-06-30 16:31:19 |
3 | user3,user4,user5 | user1 | java | 2022-06-30 16:31:22 |
4 | user7,user8 | user2 | neovim | 2022-06-30 16:31:53 |
6 | user,user11 | good | very | 2022-06-30 16:38:18 |
发现此时查询的数据就不准备了,userid越是短的,查的越不精确。
可行的办法
首先说明,可能不是最好的解决办法,仅供参考。如果您有更好的办法,欢迎评论区交流。
help_topic
开始之前我们先简答的了解一下help_topic
,主要是用来把一行变成多行的。
select substring_index(substring_index('82,83,84,85,86', ',', help_topic_id + 1), ',', -1) as Id
from mysql.help_topic
where help_topic_id < (length('82,83,84,85,86') - length(replace('82,83,84,85,86', ',', '')) + 1);
执行结果:
Id |
---|
82 |
83 |
84 |
85 |
86 |
解析
乍一看比较绕,我尽量写详细一些。
substring_index
的作用:取得目标字符串左侧第n个分割符左侧的部分,n为负时返回右侧第n个的右部分。help_topic
是数据库mysql
的一个表,该表提供查询帮助主题给定关键字的详细内容(详细帮助信息)
表字段含义:help_topic_id
:帮助主题详细信息在表记录中对应的IDname
:帮助主题给定的关键字名称。help_category_id
:帮助主题类别ID,与help_category表中的help_category_id字段值相等。description
:帮助主题的详细信息(这里就是我们通常查询帮助信息真正想看的内容,例如:告诉我们某某语句如何使用的语法与注意事项等)。example
:帮助主题的示例信息(告诉我们语句如何使用的示例)。url
:该帮助主题对应在MySQL官方在线手册中的URL链接地址。
ps:这条sql语句其实跟help_topic表没有什么关系,仅仅是借用了help_topic表的help_topic_id的值为(0,1,2,…),因此在本数据库中建立一个仅含ID字段的表进行关联,同样可以实现转多行效果
where 查询条件部分
(length('82,83,84,85,86') - length(replace('82,83,84,85,86', ',', '')) + 1)
看着很长,其实就是为了计算,
分隔的部分信息数量。也就是,
的数量+1。其实最终目标也只是得到了一个0,1,2,3,4的列表。有这样信息,就可以用来截取字符串了。
可以把这个sql一段一段执行,直至完全理解。
最终实现
SELECT
message_id,
substring_index( substring_index( msg.receiver, ',', topic.help_topic_id + 1 ), ',',- 1 ) AS receiver,
sender,
message,
create_time
FROM
t_message msg
JOIN mysql.help_topic topic ON topic.help_topic_id < ( length( msg.receiver ) - length( REPLACE ( msg.receiver, ',', '' ) ) + 1 );
查询结果如下:
message_id | receiver | sender | message | create_time |
---|---|---|---|---|
1 | user1 | system | hello | 2022-06-30 16:30:12 |
1 | user2 | system | hello | 2022-06-30 16:30:12 |
2 | user1 | system | world | 2022-06-30 16:31:19 |
2 | user3 | system | world | 2022-06-30 16:31:19 |
3 | user3 | user1 | java | 2022-06-30 16:31:22 |
3 | user4 | user1 | java | 2022-06-30 16:31:22 |
3 | user5 | user1 | java | 2022-06-30 16:31:22 |
4 | user7 | user2 | neovim | 2022-06-30 16:31:53 |
4 | user8 | user2 | neovim | 2022-06-30 16:31:53 |
5 | itkey | system | itkey | 2022-06-30 16:32:17 |
5 | lxyoucan | system | itkey | 2022-06-30 16:32:17 |
6 | user | good | very | 2022-06-30 16:38:18 |
6 | user11 | good | very | 2022-06-30 16:38:18 |
得到这个表以后,查询就比较简单了。我比较担心的是,性能可能不会特别的高。
这时候我们还按user来查询,写法如下:
select * from (
SELECT message_id,
substring_index(substring_index(msg.receiver, ',', topic.help_topic_id + 1), ',',
- 1) AS receiver,
sender,
message,
create_time
FROM t_message msg
JOIN mysql.help_topic topic ON topic.help_topic_id <
(length(msg.receiver) - length(REPLACE(msg.receiver, ',', '')) + 1)
) as tmsg where tmsg.receiver='user';
message_id | receiver | sender | message | create_time |
---|---|---|---|---|
6 | user | good | very | 2022-06-30 16:38:18 |
这次的查询结果就是正确的了。
减少子查询的使用,可以写成如下:
SELECT
message_id,
sender,
message,
create_time
FROM
t_message msg
JOIN mysql.help_topic topic ON topic.help_topic_id < ( length( msg.receiver ) - length( REPLACE ( msg.receiver, ',', '' ) ) + 1 )
where substring_index( substring_index( msg.receiver, ',', topic.help_topic_id + 1 ), ',',- 1 ) = 'user';
查询结果:
message_id | sender | message | create_time |
---|---|---|---|
6 | good | very | 2022-06-30 16:38:18 |
总结
最终方案的准确性应该是没有问题了,但是性能方面还是有优化的空间的。
参考
边栏推荐
- [daily question] dichotomy - find a single dog (Bushi)
- [mathematical logic] propositional logic (judgment of the correctness of propositional logic reasoning | formal structure is eternal truth - equivalent calculus | deduction from premise - logical reas
- 2022-07-02:以下go语言代码输出什么?A:编译错误;B:Panic;C:NaN。 package main import “fmt“ func main() { var a =
- [Yu Yue education] reference materials of political communication science of Communication University of China
- 2022-07-02: what is the output of the following go language code? A: Compilation error; B:Panic; C:NaN。 package main import “fmt“ func main() { var a =
- Is it better to speculate in the short term or the medium and long term? Comparative analysis of differences
- IPv6 transition technology-6to4 manual tunnel configuration experiment -- Kuige of Shangwen network
- Cnopendata China Customs Statistics
- 在 .NET 6 项目中使用 Startup.cs
- 国产PC系统完成闭环,替代美国软硬件体系的时刻已经到来
猜你喜欢
Mila, University of Ottawa | molecular geometry pre training with Se (3) invariant denoising distance matching
2022 tea master (primary) examination questions and tea master (primary) examination question bank
TCP, the heavyweight guest in tcp/ip model -- Kuige of Shangwen network
2022 tea master (intermediate) examination questions and analysis and tea master (intermediate) practical examination video
Makefile demo
JS实现图片懒加载
Web会话管理安全问题
When writing a web project, SmartUpload is used for file upload and new string () is used for transcoding, but in the database, there will still be random codes similar to poker
The latest analysis of the main principals of hazardous chemical business units in 2022 and the simulated examination questions of the main principals of hazardous chemical business units
如何迈向IPv6之IPv6过渡技术-尚文网络奎哥
随机推荐
记一次 .NET 差旅管理后台 CPU 爆高分析
深潜Kotlin协程(十九):Flow 概述
2022 polymerization process examination questions and polymerization process examination skills
Separable bonds and convertible bonds
深潜Kotlin协程(二十):构建 Flow
Esp32 series (3): GPIO learning (take simple GPIO input and output, ADC, DAC as examples)
The 10th China Cloud Computing Conference · China Station: looking forward to the trend of science and technology in the next decade
Makefile demo
【毕业季·进击的技术er】职场人的自白
释放数据力量的Ceph-尚文网络xUP楠哥
2022 tea master (intermediate) examination questions and analysis and tea master (intermediate) practical examination video
Deep dive kotlin synergy (19): flow overview
Interaction free shell programming
Nat. Comm. | 使用Tensor-cell2cell对细胞通讯进行环境感知去卷积
Appium自动化测试框架
"Final review" 16/32-bit microprocessor (8086) basic register
2022 tea master (intermediate) examination questions and analysis and tea master (intermediate) practical examination video
第十届中国云计算大会·中国站:展望未来十年科技走向
[brush questions] most elements (super water king problem)
MPLS setup experiment