任何人都可以在MySQL IN子句中解释这个逻辑并帮助我理解这个问题
我有一个用户表,这个表用户属于一个或多个组。 组表主键引用在users表中以逗号(,)分隔值更新,如下所示
Query 1. SELECT * FROM user;
+---------+-----------+-------------------------+-----------+
| user_id | user_name | user_email | group_id |
+---------+-----------+-------------------------+-----------+
| 1 | suresh | xxxx@yyyyyyyyyy.com | 22 |
| 2 | sundar | s7sundera@gmail.com | 2 |
| 3 | tester | xxxxxxxx@yyyyyyyyyy.com | 1,2,3,4 |
| 4 | gail | zzzzzz@gmail.com | 1,2,3,4,5 |
+---------+-----------+-------------------------+-----------+
如果我在MySQL中使用IN子句和组id值为2,我只得到一个结果
Query 2. SELECT * FROM user WHERE group_id IN(2)
+---------+-----------+---------------------+----------+
| user_id | user_name | user_email | group_id |
+---------+-----------+---------------------+----------+
| 2 | sundar | s7sundera@gmail.com | 2 |
+---------+-----------+---------------------+----------+
如果我在MySQL中使用IN子句和组ID值为(1,2),我得到了三个结果
Query 3. SELECT * FROM user WHERE group_id IN(1,2)
+---------+-----------+-------------------------+-----------+
| user_id | user_name | user_email | group_id |
+---------+-----------+-------------------------+-----------+
| 2 | sundar | s7sundera@gmail.com | 2 |
| 3 | tester | xxxxxxxx@yyyyyyyyyy.com | 1,2,3,4 |
| 4 | gail | zzzzzz@gmail.com | 1,2,3,4,5 |
+---------+-----------+-------------------------+-----------+
我想让组ID 2用户喜欢以下输出,但它没有按预期工作
如果我使用此查询,我需要获得查询3结果是否可能?
SELECT * FROM user WHERE group_id IN(2)
答案 0 :(得分:3)
这个评论太长了,但您需要重新考虑当前的表格设计。您不应将group_id
值存储为逗号分隔列表。
您的表格结构应类似于以下内容:
create table user
(
user_id int, PK
user_name varchar(50),
user_email varchar(100)
);
create table groups
(
group_id int, PK
group_name varchar(10)
);
create table user_group
(
user_id int,
group_id int
);
user_group
表将包含user_id
和group_id
的主键,因此您无法获得重复项,然后这些列应该是相应表的外键。此表允许您为每个user_id分配多个组。
然后当您查询表时,查询将是:
select u.user_id,
u.user_name,
u.user_email,
g.group_id
from user u
inner join user_group ug
on u.user_id = ug.user_id
inner join groups g
on ug.group_id = g.group_id
如果您需要用于显示目的,请在逗号分隔列表中显示group_id
值,您可以使用GROUP_CONCAT()
:
select u.user_id,
u.user_name,
u.user_email,
group_concat(g.group_id order by g.group_id) group_id
from user u
inner join user_group ug
on u.user_id = ug.user_id
inner join groups g
on ug.group_id = g.group_id
group by u.user_id, u.user_name, u.user_email
如果您重新设计表格,那么当您搜索它时会变得更容易:
select u.user_id,
u.user_name,
u.user_email,
g.group_id
from user u
inner join user_group ug
on u.user_id = ug.user_id
inner join groups g
on ug.group_id = g.group_id
where g.group_id in (1, 2)
答案 1 :(得分:2)
将1,2
传递给IN
运算符时,您需要1
和2
;这就是它将返回所有三个结果的原因。如果您的列中包含逗号分隔值,则表示您违反了普通表单;因为每列不应包含多个值。如果要在多值逗号分隔列中查找单个值,则可以使用FIND_IN_SET
。
规范化架构如下所示:
+---------+-----------+-------------------------+ | user_id | user_name | user_email | +---------+-----------+-------------------------+ | 2 | sundar | s7sundera@gmail.com | | 3 | tester | xxxxxxxx@yyyyyyyyyy.com | | 4 | gail | zzzzzz@gmail.com | +---------+-----------+-------------------------+ +---------+-----------+ | user_id | group_id | +---------+-----------+ | 2 | 2 | | 3 | 1 | | 3 | 2 | | 3 | 3 | | 3 | 4 | | 4 | 1 | | 4 | 2 | | 4 | 3 | | 4 | 4 | | 4 | 5 | +---------+-----------+ +----------+ | group_id | +----------+ | 1 | | 2 | | 3 | | 4 | +----------+
答案 2 :(得分:2)
MySQL不会将逗号分隔列表视为字符串。执行WHERE group_id IN(2)
后,它会将group_id
转换为INT
,因此可以将其与2
进行比较。
当转换为INT
时,MySQL将停在第一个非数字字符处。
例如,'1,2,3,4,5' IN (2)
变为1 IN (2)
。这是假的。
您可以尝试使用FIND_IN_SET
来执行您想要的操作,但效率不高(因为它不能使用索引;它需要读取每一行以查看是否它匹配)。
WHERE FIND_IN_SET(2, group_id)
要搜索多行,请使用OR
。
WHERE FIND_IN_SET(1, group_id) OR FIND_IN_SET(2, group_id)
正确的方法是创建一个“链接表”,其中包含每个用户的一行(或多行),显示他们所在的组。
答案 3 :(得分:1)
查询的逻辑是什么?SELECT * FROM user WHERE group_id IN(1,2);
?
(1,2)
groud_id
正在进行数字比较我要呈现给你的东西可能看起来很不正统,但请跟我来......
这是一个查询,它将获得group_ids中包含1和2的每一行:
SELECT user.* FROM
(SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
FROM user) U WHERE LOCATE(',2,',group_ids)) U1
INNER JOIN
(SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
FROM user) U WHERE LOCATE(',4,',group_ids)) U2
ON U1.id = U2.id
INNER JOIN user ON user.id = U2.id;
以下是创建我们的示例数据的代码
DROP DATABASE IF EXISTS sundar;
CREATE DATABASE sundar;
use sundar
CREATE TABLE user
(
id int not null auto_increment,
user_name VARCHAR(30),
user_email VARCHAR(70),
group_id VARCHAR(128),
PRIMARY KEY (id)
);
INSERT INTO user (user_name,user_email,group_id) VALUES
('suresh' , 'xxxx@yyyyyyyyyy.com' ,'22'),
('sundar' , 's7sundera@gmail.com' ,'2'),
('tester' , 'xxxxxxxx@yyyyyyyyyy.com' ,'1,2,3,4'),
('gail' , 'zzzzzz@gmail.com' ,'1,2,3,4,5');
SELECT * FROM user;
让我们创建您的样本
mysql> DROP DATABASE IF EXISTS sundar;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE DATABASE sundar;
Query OK, 1 row affected (0.00 sec)
mysql> use sundar
Database changed
mysql> CREATE TABLE user
-> (
-> id int not null auto_increment,
-> user_name VARCHAR(30),
-> user_email VARCHAR(70),
-> group_id VARCHAR(128),
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO user (user_name,user_email,group_id) VALUES
-> ('suresh' , 'xxxx@yyyyyyyyyy.com' ,'22'),
-> ('sundar' , 's7sundera@gmail.com' ,'2'),
-> ('tester' , 'xxxxxxxx@yyyyyyyyyy.com' ,'1,2,3,4'),
-> ('gail' , 'zzzzzz@gmail.com' ,'1,2,3,4,5');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql>
这就是它的样子
mysql> SELECT * FROM user;
+----+-----------+-------------------------+-----------+
| id | user_name | user_email | group_id |
+----+-----------+-------------------------+-----------+
| 1 | suresh | xxxx@yyyyyyyyyy.com | 22 |
| 2 | sundar | s7sundera@gmail.com | 2 |
| 3 | tester | xxxxxxxx@yyyyyyyyyy.com | 1,2,3,4 |
| 4 | gail | zzzzzz@gmail.com | 1,2,3,4,5 |
+----+-----------+-------------------------+-----------+
4 rows in set (0.00 sec)
mysql>
同样,这是一个混乱的查询,可以得到你想要的东西:
SELECT user.* FROM
(SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
FROM user) U WHERE LOCATE(',1,',group_ids)) U1
INNER JOIN
(SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
FROM user) U WHERE LOCATE(',2,',group_ids)) U2
ON U1.id = U2.id
INNER JOIN user ON user.id = U2.id;
这里执行:
mysql> SELECT user.* FROM
-> (SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
-> FROM user) U WHERE LOCATE(',1,',group_ids)) U1
-> INNER JOIN
-> (SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
-> FROM user) U WHERE LOCATE(',2,',group_ids)) U2
-> ON U1.id = U2.id
-> INNER JOIN user ON user.id = U2.id;
+----+-----------+-------------------------+-----------+
| id | user_name | user_email | group_id |
+----+-----------+-------------------------+-----------+
| 3 | tester | xxxxxxxx@yyyyyyyyyy.com | 1,2,3,4 |
| 4 | gail | zzzzzz@gmail.com | 1,2,3,4,5 |
+----+-----------+-------------------------+-----------+
2 rows in set (0.00 sec)
mysql>
好的,如何寻找(2,4)
?
mysql> SELECT user.* FROM
-> (SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
-> FROM user) U WHERE LOCATE(',2,',group_ids)) U1
-> INNER JOIN
-> (SELECT * FROM (SELECT id,CONCAT(',',group_id ,',') group_ids
-> FROM user) U WHERE LOCATE(',4,',group_ids)) U2
-> ON U1.id = U2.id
-> INNER JOIN user ON user.id = U2.id;
+----+-----------+-------------------------+-----------+
| id | user_name | user_email | group_id |
+----+-----------+-------------------------+-----------+
| 3 | tester | xxxxxxxx@yyyyyyyyyy.com | 1,2,3,4 |
| 4 | gail | zzzzzz@gmail.com | 1,2,3,4,5 |
+----+-----------+-------------------------+-----------+
2 rows in set (0.00 sec)
mysql>
看起来很有效。
试一试!!!