当前位置:网站首页>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 |
总结
最终方案的准确性应该是没有问题了,但是性能方面还是有优化的空间的。
参考
边栏推荐
- [mathematical logic] predicate logic (predicate logic basic equivalent | eliminate quantifier equivalent | quantifier negative equivalent | quantifier scope contraction expansion equivalent | quantifi
- Filter
- 编译文件时报错:错误: 编码GBK的不可映射字符
- Deep dive kotlin synergy (19): flow overview
- Social phobia of contemporary young people (II)
- 【全民编程】《软件编程-讲课视频》【零基础入门到实战应用】
- [mathematical logic] propositional logic (equivalent calculus | idempotent law | exchange law | combination law | distribution law | De Morgan law | absorption rate | zero law | identity | exclusion l
- Recursion: depth first search
- IPv6 transition technology-6to4 manual tunnel configuration experiment -- Kuige of Shangwen network
- [Apple Push] IMessage group sending condition document (push certificate) development tool pushnotification
猜你喜欢

js中#号的作用

Leetcode: dynamic planning template

leetcode:297. 二叉树的序列化与反序列化

国产PC系统完成闭环,替代美国软硬件体系的时刻已经到来

pytorch是什么?pytorch是一个软件吗?

Appium automated testing framework

300+ documents! This article explains the latest progress of multimodal learning based on transformer

【刷题篇】接雨水(一维)

js实现在可视区内,文字图片动画效果

Download and install captura and configure ffmpeg in captura
随机推荐
2.14 simulation summary
服务器无法远程连接原因分析
pytorch项目怎么跑?
How to download pytorch? Where can I download pytorch?
2022 Shandong Province safety officer C certificate examination questions and Shandong Province safety officer C certificate simulation examination question bank
pytorch开源吗?
Recursive use and multi-dimensional array object to one-dimensional array object
深潜Kotlin协程(二十):构建 Flow
js实现在可视区内,文字图片动画效果
CVPR 2022 | Dalian Technology propose un cadre d'éclairage auto - étalonné pour l'amélioration de l'image de faible luminosité de la scène réelle
2022 mobile crane driver examination registration and mobile crane driver operation examination question bank
How to connect WiFi with raspberry pie
【全民编程】《软件编程-讲课视频》【零基础入门到实战应用】
TCP/IP模型中的重磅嘉宾TCP--尚文网络奎哥
Error c2694 "void logger:: log (nvinfer1:: ilogger:: severity, const char *)": rewrite the restrictive exception specification of virtual functions than base class virtual member functions
Role of JS No
pytorch难学吗?如何学好pytorch?
CVPR 2022 | 大連理工提出自校准照明框架,用於現實場景的微光圖像增强
[brush questions] most elements (super water king problem)
Web会话管理安全问题