MSSQL 基础之以字符分隔的字符串匹配

浏览: 3462

引言

今天在SQL Server技术群里,有一位群友问到这样一个问题:表中某列数据如下图,希望能够提取值为7的记录。几经沟通之后发现,真实的需求是:希望用  SQL 将一个字段内用逗号分隔的内容分成多条记录,然后取值为7的记录。


有时候我们在设置数据库的时候,基于查询和业务的考虑会将数据以符号分隔的方式存储在一个字段内。这样的设计节省了空间,也少了一张扩展的关系表,但是却为查询带来了麻烦。关系型数据库对于这样的查询,能力略显不足。但也不是无技可施,众多的数据库大神们早已分享出了许多经典的将逗号分隔内容拆分多列的代码。在此小弟先膜拜过。

今天要分享的并非这些经典案例,而是如何在不拆分字符串内容的情况实现查询匹配。当然,仅限于单条件的查询匹配,如果是需要和字典表关联或者是多条件查询,仍要膜拜那些经典案例了。此外,在数据量大的情况下也不建议使用,以实际测试为准。

知识点

charindex

函数返回字符或者字符串在另一个字符串中的起始位置(索引从1开始)。CHARINDEX ( expression1 , expression2 [ , start_location ] )

patindex

函数返回字符或者字符串在另一个字符串或者表达式中的起始位置,PATINDEX函数支持搜索字符串中使用通配符,这使PATINDEX函数对于变化的搜索字符串很有价值(索引从1开始)。PATINDEX ( '%pattern%' , expression )。

SQL通配符


单组字符串匹配

declare @search varchar(10)
set @search = '7'
;
with tmp as
(
select 1 id, '873,874' gd_qxry
union all
select 2, '874,7,873'
union all
select 3, '7,832'
union all
select 4, '72,83,7'
)
select *
from tmp
where charindex(','+@search+',',','+gd_qxry+',')>0

有两个大家很容易想到,但是不完善的实现

a> charindex(@search,gd_qxry)>0,此实现没有考虑到如'873'这样,分隔内容包含7的情况。

b> charindex(','+@search+',',gd_qxry)>0,此实现没有考虑到如'7,873'、'873,7',7在分隔内容最前或最后的情况。

多组字符串匹配

接着这位群友又提出了,以上方案仅能实现一组字符串的匹配。假设我现在一个字段存储多组字符串,该怎么办呢。如:874,6,873|7,873,72。其实我们分析一下即可明白,所谓分组不过是又多出来一个分隔符而已,但是对于charindex来说已经是致命的了。不过,这时候得膜拜下微软的研发团队了,即生亮,又生瑜,Parindex出现了。

declare @search varchar(10)
set @search = '7'
;
with tmp as
(
select 1 id, '874,6,873|7,873,72' gd_qxry
union all
select 2, '874,7,873|832,73'
union all
select 3, '71,832|83,77'
union all
select 4, '72,83,7|872,33'
)
select *
from tmp
where patindex('%[,|]'+@search+'[,|]%',','+gd_qxry+',')>0

Patindex的妙处在于支持通配符。我一度的想,要是支持正则表达式该有多好。不过SQL也不是不能,CLR都支持了还有什么是不能的。

PS

以上仅是本人臆想的测试数据,欢迎各位看官提出异常情况批评指正,在此叩谢。

推荐 3
本文由 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

6 个评论

只想弱弱的问一句,如果我想查询出来含7,或者含874的怎么办?
悟

回复 flybi_xw

写两个条件或就可以了吧
悟

回复 flybi_xw

开篇我也说了,什么情况适合这样,再复杂的情况我们就可以符号分隔的内容拆分多行了
flybi_xw

flybi_xw 回复

写两个条件,感觉有点不可取,万一,是个多选条件,100个选项值呢。哈哈哈,拆分多行匹配,就是效率有点让人郁闷。目前还没有什么更好的招。
悟

回复 flybi_xw

其实100个选项值用这个办法也没有关系的,把这100个选项值放在一个临时表或表变量里和主表做关联就可以了。写在on条件里。
flybi_xw

flybi_xw 回复

对的

要回复文章请先登录注册