SELECT FROM Table WHERE 不部分的确切数字在字符串中 SQL
SELECT FROM Table WHERE exact number not partial is in a string SQL
我有一个 table,其中包含一串由逗号分隔的数字。
我想从 table 中检索行,其中字符串中包含精确数字而不是部分数字。
示例:
CREATE TABLE IF NOT EXISTS `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`uids` text NOT NULL,
`islive` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `teams` (`id`, `name`, `uids`, `islive`) VALUES
(1, 'Test Team', '1,2,8', 1),
(3, 'Test Team 2', '14,18,19', 1),
(4, 'Another Team', '1,8,20,23', 1);
我想搜索字符串中 1 的位置。
目前,如果我使用 Contains 或 LIKE,它会带回所有带 1 的行,但 18、19 等不是 1,但其中确实有 1。
我需要做正则表达式吗?
你或许可以用 OR
SELECT ...
WHERE uids LIKE '1,%'
OR uids LIKE '%,1'
OR uids LIKE '%, 1'
OR uids LIKE '%,1,%'
OR uids = '1'
我会搜索您要搜索的 ID 的所有四个可能位置:
- 作为列表的唯一元素。
- 作为列表的第一个元素。
- 作为列表的最后一个元素。
- 作为列表的内部元素。
查询如下所示:
select *
from teams
where uids = '1' -- only
or uids like '1,%' -- first
or uids like '%,1' -- last
or uids like '%,1,%' -- inner
你只需要1个条件:
select *
from teams
where concat(',', uids, ',') like '%,1,%'
您没有指定您正在使用哪个版本的 SQL 服务器,但是如果您使用的是 2016+,您可以访问在这种情况下可以使用的 STRING_SPLIT 功能.这是一个例子:
CREATE TABLE #T
(
id int,
string varchar(20)
)
INSERT INTO #T
SELECT 1, '1,2,8' UNION
SELECT 2, '14,18,19' UNION
SELECT 3, '1,8,20,23'
SELECT * FROM #T
CROSS APPLY string_split(string, ',')
WHERE value = 1
您 SQL Fiddle 使用 MySQL 并且您的语法与 MySQL 一致。有一个内置函数可以使用:
select t.*
from teams t
where find_in_set(1, uids) > 0;
话虽如此,请修复您的数据模型,这样您就不会在单个列中存储列表。不好意思说的这么大声,只是数据库设计的一个重要原则。
您应该有一个名为 teamUsers
的 table,每个团队和该团队中的每个用户一行。您存储数据的方法不好的原因有很多:
- 数字应存储为数字,而不是字符串。
- 列应包含单个值。
- 应正确声明外键关系。
- SQL(一般而言)具有糟糕的字符串处理功能。
- 生成的查询无法优化。
- 按顺序列出
uid
或删除重复项等简单的事情都不必要地困难。
我有一个 table,其中包含一串由逗号分隔的数字。
我想从 table 中检索行,其中字符串中包含精确数字而不是部分数字。
示例:
CREATE TABLE IF NOT EXISTS `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`uids` text NOT NULL,
`islive` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `teams` (`id`, `name`, `uids`, `islive`) VALUES
(1, 'Test Team', '1,2,8', 1),
(3, 'Test Team 2', '14,18,19', 1),
(4, 'Another Team', '1,8,20,23', 1);
我想搜索字符串中 1 的位置。
目前,如果我使用 Contains 或 LIKE,它会带回所有带 1 的行,但 18、19 等不是 1,但其中确实有 1。
我需要做正则表达式吗?
你或许可以用 OR
SELECT ...
WHERE uids LIKE '1,%'
OR uids LIKE '%,1'
OR uids LIKE '%, 1'
OR uids LIKE '%,1,%'
OR uids = '1'
我会搜索您要搜索的 ID 的所有四个可能位置:
- 作为列表的唯一元素。
- 作为列表的第一个元素。
- 作为列表的最后一个元素。
- 作为列表的内部元素。
查询如下所示:
select *
from teams
where uids = '1' -- only
or uids like '1,%' -- first
or uids like '%,1' -- last
or uids like '%,1,%' -- inner
你只需要1个条件:
select *
from teams
where concat(',', uids, ',') like '%,1,%'
您没有指定您正在使用哪个版本的 SQL 服务器,但是如果您使用的是 2016+,您可以访问在这种情况下可以使用的 STRING_SPLIT 功能.这是一个例子:
CREATE TABLE #T
(
id int,
string varchar(20)
)
INSERT INTO #T
SELECT 1, '1,2,8' UNION
SELECT 2, '14,18,19' UNION
SELECT 3, '1,8,20,23'
SELECT * FROM #T
CROSS APPLY string_split(string, ',')
WHERE value = 1
您 SQL Fiddle 使用 MySQL 并且您的语法与 MySQL 一致。有一个内置函数可以使用:
select t.*
from teams t
where find_in_set(1, uids) > 0;
话虽如此,请修复您的数据模型,这样您就不会在单个列中存储列表。不好意思说的这么大声,只是数据库设计的一个重要原则。
您应该有一个名为 teamUsers
的 table,每个团队和该团队中的每个用户一行。您存储数据的方法不好的原因有很多:
- 数字应存储为数字,而不是字符串。
- 列应包含单个值。
- 应正确声明外键关系。
- SQL(一般而言)具有糟糕的字符串处理功能。
- 生成的查询无法优化。
- 按顺序列出
uid
或删除重复项等简单的事情都不必要地困难。