如何计算SQL varchar中某个子string的出现次数?

我有一个列的值格式为a,b,c,d。 有没有一种方法来计算在T-SQL中的值的逗号数量?

首先想到的方法是间接地通过用空stringreplace逗号并比较长度来实现

Declare @string varchar(1000) Set @string = 'a,b,c,d' select len(@string) - len(replace(@string, ',', '')) 

cmsjr的答案的快速扩展适用于多个字符以上的string。

 CREATE FUNCTION dbo.CountOccurancesOfString ( @searchString nvarchar(max), @searchTerm nvarchar(max) ) RETURNS INT AS BEGIN return (LEN(@searchString)-LEN(REPLACE(@searchString,@searchTerm,'')))/LEN(@searchTerm) END 

用法:

 SELECT * FROM MyTable where dbo.CountOccurancesOfString(MyColumn, 'MyString') = 1 

您可以比较string的长度和逗号被删除的长度。

 len(value) - len(replace(value,',','')) 

@csmjr的答案在某些情况下有问题。

他的回答是这样做的:

 Declare @string varchar(1000) Set @string = 'a,b,c,d' select len(@string) - len(replace(@string, ',', '')) 

这在大多数情况下工作,但是,尝试运行这个:

 DECLARE @string VARCHAR(1000) SET @string = 'a,b,c,d ,' SELECT LEN(@string) - LEN(REPLACE(@string, ',', '')) 

出于某种原因,REPLACE摆脱了最后的逗号,但也是之前的空间(不知道为什么)。 如果您期望4,则返回值为5.这是另一种方法,即使在这种特殊情况下也可以这样做:

 DECLARE @string VARCHAR(1000) SET @string = 'a,b,c,d ,' SELECT LEN(REPLACE(@string, ',', '**')) - LEN(@string) 

请注意,您不需要使用星号。 任何双字符replace都可以。 这个想法是,你为每个你要计算的angular色实例加一个字符,然后减去原来的长度。 原来的回答基本上是与奇怪的修剪副作用不同的方法。

 Declare @string varchar(1000) DECLARE @SearchString varchar(100) Set @string = 'as as df df as as as' SET @SearchString = 'as' select ((len(@string) - len(replace(@string, @SearchString, ''))) -(len(@string) - len(replace(@string, @SearchString, ''))) % 2) / len(@SearchString) 

以@ Andrew的解决scheme为基础,使用非过程式表值函数和CROSS APPLY可以获得更好的性能:

 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* Usage: SELECT t.[YourColumn], c.StringCount FROM YourDatabase.dbo.YourTable t CROSS APPLY dbo.CountOccurrencesOfString('your search string', t.[YourColumn]) c */ CREATE FUNCTION [dbo].[CountOccurrencesOfString] ( @searchString nvarchar(max), @searchTerm nvarchar(max) ) RETURNS TABLE AS RETURN SELECT (DATALENGTH(@searchString)-DATALENGTH(REPLACE(@searchString,@searchTerm,'')))/NULLIF(DATALENGTH(@searchTerm), 0) AS StringCount 
 DECLARE @records varchar(400) SELECT @records = 'a,b,c,d' select LEN(@records) as 'Before removing Commas' , LEN(@records) - LEN(REPLACE(@records, ',', '')) 'After Removing Commans' 

达雷尔李我觉得有一个很好的答案。 replaceCHARINDEX()PATINDEX() ,你也可以做一些弱regexsearchstring,也…

就像你说的@pattern

 set @pattern='%[-.|!,'+char(9)+']%' 

你为什么要这样做呢?

假设您正在将分隔文本string加载到临时表中,其中保存数据的字段类似于varchar(8000)或nvarchar(max)…

有时用数据而不是ETL(Extract-Transform-Load)进行ELT(Extract-Load-Transform)是更容易/更快的方法,一种方法是将定界的logging原样加载到登台表中,特别是如果你可能需要一个更简单的方法来查看例外的logging,而不是把它们作为SSIS包的一部分来处理……但是对于不同的线程来说,这是一场神圣的战争。

您可以使用以下存储过程来获取值。

 IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_parsedata]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[sp_parsedata] GO create procedure sp_parsedata (@cid integer,@st varchar(1000)) as declare @coid integer declare @c integer declare @c1 integer select @c1=len(@st) - len(replace(@st, ',', '')) set @c=0 delete from table1 where complainid=@cid; while (@c<=@c1) begin if (@c<@c1) begin select @coid=cast(replace(left(@st,CHARINDEX(',',@st,1)),',','') as integer) select @st=SUBSTRING(@st,CHARINDEX(',',@st,1)+1,LEN(@st)) end else begin select @coid=cast(@st as integer) end insert into table1(complainid,courtid) values(@cid,@coid) set @c=@c+1 end 

replace/ Lentesting是可爱的,但可能非常低效(特别是在内存方面)。 一个循环的简单函数将完成这项工作。

 CREATE FUNCTION [dbo].[fn_Occurences] ( @pattern varchar(255), @expression varchar(max) ) RETURNS int AS BEGIN DECLARE @Result int = 0; DECLARE @index BigInt = 0 DECLARE @patLen int = len(@pattern) SET @index = CHARINDEX(@pattern, @expression, @index) While @index > 0 BEGIN SET @Result = @Result + 1; SET @index = CHARINDEX(@pattern, @expression, @index + @patLen) END RETURN @Result END 

也许你不应该以这种方式存储数据。 在字段中存储逗号分隔列表是一种不好的做法。 IT查询效率很低。 这应该是一个相关的表格。