回答

收藏

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

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

我有以下表格:' A0 l: r' O3 e" c8 G
过滤器
2 t4 @+ s) x* R- s3 s7 N# |/ ^id | u_ids, B, f) B& B- |! T! K
1  | 1, 2, 36 d: w/ ^$ Z* }- e$ C! i
2  | 5, 65 I9 a7 K. l4 I; }
使用者
8 K+ h: `' M$ ~3 s4 @id | name
) T. k+ m; V  W3 V" y1  | Tom
  z: w! s, g! x2  | Tim
$ [: {; W/ T& }" B8 H3  | Sue; ?7 V- n* ^7 s, Y( `- ?, V) @
4  | Bruce% `7 p/ _7 t3 {. l& h
5  | Ann
1 P& }" E# h' s& G0 v5 K6  | George  ]) A  O1 T0 X, w6 o
我想运行以下选择* S! \+ c8 t3 Z
select * from users where id in (select u_ids from filters where id =1);
; H5 l9 X4 F" ~- M- O1 `! x% R- p/ e我想收到3 D! S6 o) d$ C
id | name
5 l# C) u8 m! ?1 k+ U1  | Tom' p6 s, I' t- c1 M4 \/ W, w
2  | Tim: y- F+ m  N& N$ Q  L
3  | Sue5 P: C! n# V) V5 O2 _  c' T' _7 a, `
但是我什么也没收到。
; D; F" f- o1 Q9 j* }/ p. u% L问题在于该字段u_ids是文本,因此“ in select”返回的内容类似于“ 1、2、3”(带有分号),因此 in 找不到任何值。' |# W1 {! f: z% H( {+ ^/ N) G4 M
是否可以进行强制转换或将字符串更改为数组的选项?
# O$ e. T" r: R; \6 Y                $ J5 u* M1 a6 o1 L$ v
解决方案:+ e- u3 G2 ?: G" Z
               
% P! }$ D4 Q* `" I  [; w
/ l" L$ R  y9 t5 T7 [+ H8 _7 Y5 x* `# `: _; o3 Z
                最好规范化您的架构,不要以逗号分隔列表的形式存储关系,而是为此创建一个联结表,以维护用户和过滤器之间的 m:m
& r( r* d& A/ _% V6 W多对多关系,并创建一个新表,user_filters其中包括过滤器ID和用户列id并在每行中为每个用户保存一个关联,并且过滤器就像您当前架构关系中的过滤器1中有很多用户的(1,'1, 2, 3') 情况一样
, S# S  A8 \* ]% \- Yfilter id user id# q4 i" W; s5 d; e! g
    (1, '1'),
7 _3 |- ~( X, Z    (1, '2'),
' D0 I4 h7 k  U1 m  @* S    (1, '3'),$ O0 Z, H: o, _2 X" p3 L4 O
+ k* b8 |; x, j+ k" E
示例架构将如下所示
! p+ H- C+ p! u$ z4 KCREATE TABLE user_filters
& j) F8 n. Y2 _    (`fid` int, `u_id` varchar(50))* x  u/ Y' b9 f
;
; K8 i! r* a/ y! vINSERT INTO user_filters
! P1 u* t/ t9 q# L5 M$ I. r    (`fid`, `u_id`)' D: a. }9 J7 g6 O* u+ _
VALUES0 G1 m& G; T# n" Z
    (1, '1'),
+ J3 p( V2 `# \6 ^    (1, '2'),
9 ]! }; x0 C0 y! M# k3 z; `    (1, '3'),; Y$ |  e. K9 x7 g4 J! E  S9 R
    (2, '5'),& i' J) B. H5 E4 N$ V
    (2, '5')
5 B, }" c/ `4 H* h0 S;3 W7 W5 p- @. v! e4 P1 @
CREATE TABLE filters% v6 z8 h5 p1 t; X
    (`id` int, `title` varchar(50))
/ Z& f( h. z# G; |( Z;' F: |% v: r: B  Z2 E
INSERT INTO filters
7 {+ c: t  L) v, g, ], S. G    (`id`, `title`)4 M! o- U5 r( b
VALUES
- Y  |& r- B+ n- Q    (1, 'test'),
! W% O$ e% m. i! z    (2, 'test 1')! q6 R8 `8 s% V2 [
;
- ~  [7 J0 a0 w4 t
/ Q2 G; x! O8 i- \5 V. nCREATE TABLE users  |/ c* O7 \) [- K! [
    (`id` int, `name` varchar(6))
+ i, Z+ V; K( x5 M3 F6 g7 B;. s, O  D, Q! Q9 ^  \
INSERT INTO users% D) H. Y0 p8 }. ~, [
    (`id`, `name`)' J( ]* V, n2 y/ d( ^* {
VALUES# C* D9 V: J3 Y* J9 T
    (1, 'Tom'),8 P( G8 ]8 H: a& K
    (2, 'Tim'),
# I, t& `4 \* K$ p- j; P2 E1 L    (3, 'Sue'),
9 ~0 d* }/ y  I8 q    (4, 'Bruce'),
5 |- X. W  }" D6 y    (5, 'Ann'),0 t6 \: h, l# i8 i& ~1 b- h
    (6, 'George')) c9 W9 [5 Z; M% ]4 h7 n+ N
;
* G9 `3 ^3 N' u& L对于上面的模式,您可以使用join轻松查询,下面的查询可以使用索引进行优化
0 h! f( k/ f1 r" N- _select u.*
- f  t0 w/ ^* i$ L+ Lfrom users u; W) E, C: j4 O
join user_filters uf on(uf.u_id = u.id)
' S6 ~+ x1 q6 n- b where uf.fid =1% q$ i! c- d2 u/ M2 r
样本演示$ h# N+ \. m& f- s" H; O# J
如果您无法更改自己的架构并希望坚持使用当前架构,则可以按以下方式查询,但与上述查询相比,该架构无法充分优化
4 a6 g; d5 Z  F* Fselect u.*
, ?* S+ ^' T3 L8 |0 n8 Z1 Mfrom users u
3 m4 g7 m% n3 o" H% [1 c! _8 Q1 h+ N" Vjoin filters f on(find_in_set(u.id,replace(`u_ids`,' ','')) > 0)( S6 n' E1 N" j2 k  j* T
where f.id =1
' f/ |1 D& J! B1 W样本演示
+ l1 R% ~" ?7 I* y" L  j: T: g4 i7 ^1 m数据库规范化
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则