回答

收藏

MySQL ::从逗号分隔的字符串中选择

技术问答 技术问答 54 人阅读 | 0 人回复 | 2023-09-13

我有以下表格:- R$ g0 G, G  X1 f  b1 x/ z  b: h
过滤器
, I. F$ c5 R* e6 y8 |2 ?+ Wid | u_ids1 h! X/ L! k. @, @1 [4 r
1  | 1, 2, 3
7 A* Y6 d* a& C2  | 5, 6
% I/ _* u; w9 d( s) k使用者6 p* @2 A/ `5 j& k$ Y/ c$ c
id | name
9 e' R  n$ @- Z7 T6 Z; X2 q1  | Tom
6 g. p: f; j# O. n2  | Tim
6 F! m# M9 f( y4 {0 c( N% W3  | Sue
! e$ Z, D1 G3 s% b8 `4  | Bruce
. E( N' W/ T7 B, ^8 z  U/ d+ L5  | Ann
# w) U* ?9 M* F6  | George
) I+ P8 g) D$ {8 n4 D我想运行以下选择# R( J5 K: W( L( V: L
select * from users where id in (select u_ids from filters where id =1);
- i* ^2 T# W- W2 n我想收到' Z" u6 P# q2 ~( J5 Y+ s( _
id | name
' l0 T3 I7 F7 X1 T: V3 e4 t1  | Tom
, G8 A3 P* ?; R3 O4 H- {) t3 t# M2  | Tim! p6 g$ x! Y! J' o' L' q, K
3  | Sue
3 i; m% g% G2 W# [1 u8 G  t+ q但是我什么也没收到。
) U, A  P  x  \" `: F& D/ J问题在于该字段u_ids是文本,因此“ in select”返回的内容类似于“ 1、2、3”(带有分号),因此 in 找不到任何值。
4 m* V, q+ m% c' X是否可以进行强制转换或将字符串更改为数组的选项?0 X/ n- T8 u2 p
                ! g5 n- e( ~, G* u! U2 N  `
解决方案:" m& p% k- F0 {& H: }( X
                ) E; ~* Y% U1 A! O6 |5 v

" u4 e7 ]0 @1 k
3 v6 c; E! E  V% W) b+ a                最好规范化您的架构,不要以逗号分隔列表的形式存储关系,而是为此创建一个联结表,以维护用户和过滤器之间的 m:m( p; R5 K1 P+ ^7 A
多对多关系,并创建一个新表,user_filters其中包括过滤器ID和用户列id并在每行中为每个用户保存一个关联,并且过滤器就像您当前架构关系中的过滤器1中有很多用户的(1,'1, 2, 3') 情况一样. T: c7 \! d- C- R2 P
filter id user id9 r1 K9 z" L+ M/ U
    (1, '1'),& l# _5 i- l- }" l+ |) H: u
    (1, '2'),1 v5 m0 y3 A+ j7 m+ `
    (1, '3'),
# R5 Z0 r# N; p2 E9 o# o: ?+ e: J! a! J
示例架构将如下所示4 p2 A2 e; o6 k  g/ p
CREATE TABLE user_filters
3 X/ T* t% k  ~+ Z: I: p    (`fid` int, `u_id` varchar(50))) Y8 \% g0 T- E; ]5 L6 ^; u
;  m4 V3 n" [4 w$ o4 k8 b1 x+ n3 i
INSERT INTO user_filters
' A# }3 f: r  c# N7 `9 e' e3 B    (`fid`, `u_id`)( D" K# R0 Q6 c+ c0 B
VALUES
2 a* m& r9 y& w2 a    (1, '1'),
) N1 }5 x1 `/ p, X' n/ ?    (1, '2'),% A- `* m; q( E! Y& X
    (1, '3'),8 N- Q# f" q' Q8 n9 l
    (2, '5'),
% ?! w3 U" `& M8 a* o$ Y    (2, '5')) O+ }2 ]9 W0 W4 J, d' j" d7 P$ d8 J
;
2 s1 k$ t3 K3 D8 T; p; \$ H( eCREATE TABLE filters4 v, Z/ P/ E2 R
    (`id` int, `title` varchar(50))' b* x8 l! F: I# A% k. ]! F
;! ?+ A0 m- B/ R7 J
INSERT INTO filters1 @, `& {3 }8 X- ]! \
    (`id`, `title`)
, Z( r1 b! z% I% QVALUES5 u6 H3 T! }! U$ g! Y* a
    (1, 'test'),
" h: R  p: e$ _5 A    (2, 'test 1')# X5 V1 D8 M: K+ ~
;; j, E2 O" _" I% E3 b$ E
6 q% Y. M4 u$ u$ e* w, T
CREATE TABLE users6 B) o) ]9 ?  q
    (`id` int, `name` varchar(6))8 R. v' z) r4 A/ s& ]  q
;
' B4 S" S! \- s2 x3 U' Z3 d2 M# {, }INSERT INTO users9 p9 P5 X- B* q& Y# ?
    (`id`, `name`)7 i) R6 F9 S  v7 [
VALUES
& g" J7 {2 t* O    (1, 'Tom'),
3 K2 r0 A2 {7 s/ C6 z2 U. M    (2, 'Tim'),0 C" L7 y/ x) O' E; ?
    (3, 'Sue'),
# U% D; B0 h/ r    (4, 'Bruce'),
7 L) p6 K$ b4 J$ q( u9 K7 G/ W# B    (5, 'Ann'),, l7 X- X; Z: e% `) ~3 M/ J  |3 q
    (6, 'George')0 f6 V' K% E) e$ d4 D' s
;9 w$ p& b- y' Q1 F- O
对于上面的模式,您可以使用join轻松查询,下面的查询可以使用索引进行优化
1 S/ _: ^9 U7 x# f, @5 }7 Jselect u.*
& e$ e5 y1 F6 Q  k7 I6 x5 ~from users u
6 H+ q. _- Y) n2 r2 Ijoin user_filters uf on(uf.u_id = u.id)
% e4 ?6 m  m  L where uf.fid =1
+ D- K& B- A7 r. u1 o# t: _% A样本演示' v. ?- o& n- @$ o
如果您无法更改自己的架构并希望坚持使用当前架构,则可以按以下方式查询,但与上述查询相比,该架构无法充分优化
, U5 j$ T+ n8 j9 e+ D. S: u# Mselect u.* ) a- q! A4 u2 s1 j+ l2 }5 H8 S
from users u
4 D) ^' {+ d# a( J" {, Ejoin filters f on(find_in_set(u.id,replace(`u_ids`,' ','')) > 0)3 U; O- ~+ C! g
where f.id =1$ p, \5 T; f6 u& {. G2 h
样本演示1 i% F' b1 o6 e3 j) x% a, h
数据库规范化
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则