任何人都可以在MySQL in子句中解释这一逻辑背后的原因
任何人都可以在MySQL in子句中解释这一逻辑的背后,并帮助我理解这个问题 我有一个用户表,该表的用户属于一个或多个组。 组表主键引用在users表中由逗号(,)分隔的值更新,如下所示任何人都可以在MySQL in子句中解释这一逻辑背后的原因,mysql,Mysql,任何人都可以在MySQL in子句中解释这一逻辑的背后,并帮助我理解这个问题 我有一个用户表,该表的用户属于一个或多个组。 组表主键引用在users表中由逗号(,)分隔的值更新,如下所示 Query 1. SELECT * FROM user; +---------+-----------+-------------------------+-----------+ | user_id | user_name | user_email | group_id | +--
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)
将
1,2
传递给中的操作符时,您要求1
和2
;这就是它将返回所有三个结果的原因。如果您有一个值以逗号分隔的列,则违反了标准格式;因为每列不应包含多个值。如果要在多值逗号分隔列中查找单个值,则可以使用find\u 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 |
+----------+
+---------+-----------+-------------------------+
|用户id |用户名称|用户电子邮件|
+---------+-----------+-------------------------+
|2 | sundar |s7sundera@gmail.com |
|3 |测试仪|xxxxxxxx@yyyyyyyyyy.com |
|4 |盖尔|zzzzzz@gmail.com |
+---------+-----------+-------------------------+
+---------+-----------+
|用户id |组id|
+---------+-----------+
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 4 | 1 |
| 4 | 2 |
| 4 | 3 |
| 4 | 4 |
| 4 | 5 |
+---------+-----------+
+----------+
|组id|
+----------+
| 1 |
| 2 |
| 3 |
| 4 |
+----------+ 将1,2
传递给中的操作符时,您要求1
和2
;这就是它将返回所有三个结果的原因。如果您有一个值以逗号分隔的列,则违反了标准格式;因为每列不应包含多个值。如果要在多值逗号分隔列中查找单个值,则可以使用find\u 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 |
+----------+
+---------+-----------+-------------------------+
|用户id |用户名称|用户电子邮件|
+---------+-----------+-------------------------+
|2 | sundar |s7sundera@gmail.com |
|3 |测试仪|xxxxxxxx@yyyyyyyyyy.com |
|4 |盖尔|zzzzzz@gmail.com |
+---------+-----------+-------------------------+
+---------+-----------+
|用户id |组id|
+---------+-----------+
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 4 | 1 |
| 4 | 2 |
| 4 | 3 |
| 4 | 4 |
| 4 | 5 |
+---------+-----------+
+----------+
|组id|
+----------+
| 1 |
| 2 |
| 3 |
| 4 |
+----------+ 这太长了,不能作为注释,但您需要重新考虑当前的表设计。您不应将组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\u-group
表将同时具有user\u-id
和group\u-id
的主键,因此您无法获得重复项,然后这些列应该是相应表的外键。此表允许您为每个用户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\u id
值,可以使用group\u CONCAT()
:
看
如果重新设计表格,则搜索时会变得容易得多:
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)
请参见这太长,不能作为注释,但您需要重新考虑当前的表设计。您不应将组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\u-group
表将同时具有user\u-id
和group\u-id
的主键,因此您无法获得重复项,然后这些列应该是相应表的外键。此表允许您为每个用户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\u id
值,可以使用group\u CONCAT()
:
看
如果重新设计表格,则搜索时会变得容易得多:
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)
请参见MySQL将逗号分隔的列表视为字符串以外的任何东西。当您在(2)中执行WHERE group\u id
时,它会将group\u id
转换为INT
,以便与2
进行比较
当强制转换为INT
时,MySQL在第一个非数字字符处停止
例如,(2)
中的'1,2,3,4,5'变为(2)
中的1。这是错误的
您可以尝试使用FIND_IN_SET
来执行所需操作,但效率不高(因为它无法使用索引;它需要读取每一行以查看是否匹配)
要搜索多行,请使用或
WHERE FIND_IN_SET(1, group_id) OR FIND_IN_SET(2, group_id)
正确的方法是为每个用户创建一个“链接表”,其中包含一(或多)行,显示他们所在的组。MySQL不将逗号分隔的列表视为字符串以外的任何内容。当您在(2)中执行WHERE group\u id
时,它会将group\u id
转换为INT
,以便与2
进行比较
当铸造到
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>
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>