답변:
가장 먼저 떠오르는 방법은 쉼표를 빈 문자열로 바꾸고 길이를 비교하여 간접적으로 수행하는 것입니다.
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
LTRIM
문자열을 다음과 같이 감싸지 않겠습니까 SELECT LEN(RTRIM(@string)) - LEN(REPLACE(RTRIM(@string), ',', ''))
?
더 많은 문자의 문자열에 작동하는 cmsjr의 답변을 빠르게 확장합니다.
CREATE FUNCTION dbo.CountOccurrencesOfString
(
@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.CountOccurrencesOfString(MyColumn, 'MyString') = 1
dbo.CountOccurancesOfString( 'blah ,', ',')
1 대신 2를 반환 dbo.CountOccurancesOfString( 'hello world', ' ')
하고 0으로 나누면 실패합니다.
DATALENGTH()/2
명확하지 않은 문자 크기 때문에 까다 롭습니다. 간단하고 정확한 방법 은 stackoverflow.com/a/11080074/1094048 을 참조하십시오.
@Andrew의 솔루션을 기반으로 비 절차 적 테이블 반환 함수와 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]
(
@searchTerm nvarchar(max),
@searchString nvarchar(max)
)
RETURNS TABLE
AS
RETURN
SELECT (DATALENGTH(@searchString)-DATALENGTH(REPLACE(@searchString,@searchTerm,'')))/NULLIF(DATALENGTH(@searchTerm), 0) AS StringCount
@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)
별표를 사용할 필요는 없습니다. 두 문자로 대체됩니다. 계산하는 캐릭터의 각 인스턴스에 대해 문자열을 한 문자 씩 늘리고 원본의 길이를 빼는 것이 좋습니다. 기본적으로 이상한 트리밍 부작용이없는 원래 답변의 반대 방법입니다.
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)
대럴 리 꽤 좋은 답변이 있다고 생각합니다. 교체 CHARINDEX()
로 PATINDEX()
, 당신은 몇 가지 약을 할 수 regex
도 캐릭터에 따라 검색을 ...
마찬가지로 이것을 사용한다고 가정 해보십시오 @pattern
.
set @pattern='%[-.|!,'+char(9)+']%'
왜 이런 미친 짓을하고 싶습니까?
구분 된 텍스트 문자열을 준비 테이블에로드한다고 가정합니다. 여기서 데이터를 보유하는 필드는 varchar (8000) 또는 nvarchar (max)와 같습니다.
때때로 ETL (Extract-Transform-Load)이 아닌 데이터를 사용하여 ELT (Extract-Load-Transform)를 수행하는 것이 더 쉽고 빠르며,이를 수행하는 한 가지 방법은 구분 된 레코드를 스테이징 테이블에 그대로로드하는 것입니다. SSIS 패키지의 일부로 다루지 않고 예외적 인 레코드를 볼 수있는 더 간단한 방법을 원할 수도 있습니다. 그러나 그것은 다른 스레드와의 전쟁입니다.
다음은 단일 문자 검색과 다중 문자 검색에 대한 트릭을 수행해야합니다.
CREATE FUNCTION dbo.CountOccurrences
(
@SearchString VARCHAR(1000),
@SearchFor VARCHAR(1000)
)
RETURNS TABLE
AS
RETURN (
SELECT COUNT(*) AS Occurrences
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY O.object_id) AS n
FROM sys.objects AS O
) AS N
JOIN (
VALUES (@SearchString)
) AS S (SearchString)
ON
SUBSTRING(S.SearchString, N.n, LEN(@SearchFor)) = @SearchFor
);
GO
---------------------------------------------------------------------------------------
-- Test the function for single and multiple character searches
---------------------------------------------------------------------------------------
DECLARE @SearchForComma VARCHAR(10) = ',',
@SearchForCharacters VARCHAR(10) = 'de';
DECLARE @TestTable TABLE
(
TestData VARCHAR(30) NOT NULL
);
INSERT INTO @TestTable
(
TestData
)
VALUES
('a,b,c,de,de ,d e'),
('abc,de,hijk,,'),
(',,a,b,cde,,');
SELECT TT.TestData,
CO.Occurrences AS CommaOccurrences,
CO2.Occurrences AS CharacterOccurrences
FROM @TestTable AS TT
OUTER APPLY dbo.CountOccurrences(TT.TestData, @SearchForComma) AS CO
OUTER APPLY dbo.CountOccurrences(TT.TestData, @SearchForCharacters) AS CO2;
이 함수는 숫자 테이블 (dbo.Nums)을 사용하여 조금 단순화 할 수 있습니다.
RETURN (
SELECT COUNT(*) AS Occurrences
FROM dbo.Nums AS N
JOIN (
VALUES (@SearchString)
) AS S (SearchString)
ON
SUBSTRING(S.SearchString, N.n, LEN(@SearchFor)) = @SearchFor
);
이 코드를 사용하면 완벽하게 작동합니다. 두 개의 매개 변수를 허용하는 sql 함수를 만들었습니다. 첫 번째 매개 변수는 검색하려는 긴 문자열이며 최대 1500 자의 문자열 길이를 허용 할 수 있습니다 (물론 확장하거나 텍스트 데이터 유형으로 변경할 수도 있음) ). 그리고 두 번째 매개 변수는 발생 횟수를 계산하려는 하위 문자열입니다 (길이는 최대 200 자입니다. 물론 필요에 따라 변경할 수 있습니다). 그리고 출력은 정수이고, 주파수의 수를 나타냅니다 ..... 즐길 수 있습니다.
CREATE FUNCTION [dbo].[GetSubstringCount]
(
@InputString nvarchar(1500),
@SubString NVARCHAR(200)
)
RETURNS int
AS
BEGIN
declare @K int , @StrLen int , @Count int , @SubStrLen int
set @SubStrLen = (select len(@SubString))
set @Count = 0
Set @k = 1
set @StrLen =(select len(@InputString))
While @K <= @StrLen
Begin
if ((select substring(@InputString, @K, @SubStrLen)) = @SubString)
begin
if ((select CHARINDEX(@SubString ,@InputString)) > 0)
begin
set @Count = @Count +1
end
end
Set @K=@k+1
end
return @Count
end
마지막으로 입력에 char 접두사와 접미사를 추가하여 가능한 모든 상황을 다루어야하는이 함수를 작성하십시오. 이 문자는 검색 매개 변수에 포함 된 문자와 다른 것으로 평가되므로 결과에 영향을 미치지 않습니다.
CREATE FUNCTION [dbo].[CountOccurrency]
(
@Input nvarchar(max),
@Search nvarchar(max)
)
RETURNS int AS
BEGIN
declare @SearhLength as int = len('-' + @Search + '-') -2;
declare @conteinerIndex as int = 255;
declare @conteiner as char(1) = char(@conteinerIndex);
WHILE ((CHARINDEX(@conteiner, @Search)>0) and (@conteinerIndex>0))
BEGIN
set @conteinerIndex = @conteinerIndex-1;
set @conteiner = char(@conteinerIndex);
END;
set @Input = @conteiner + @Input + @conteiner
RETURN (len(@Input) - len(replace(@Input, @Search, ''))) / @SearhLength
END
용법
select dbo.CountOccurrency('a,b,c,d ,', ',')
이 T-SQL 코드는 문장 @s에서 패턴 @p를 모두 찾아서 인쇄합니다. 나중에 문장에 대한 처리를 수행 할 수 있습니다.
declare @old_hit int = 0
declare @hit int = 0
declare @i int = 0
declare @s varchar(max)='alibcalirezaalivisualization'
declare @p varchar(max)='ali'
while @i<len(@s)
begin
set @hit=charindex(@p,@s,@i)
if @hit>@old_hit
begin
set @old_hit =@hit
set @i=@hit+1
print @hit
end
else
break
end
결과 : 1 6 13 20
SQL Server 2017 용
declare @hits int = 0;
set @hits = (select count(*) from (select value from STRING_SPLIT('F609,4DFA,8499',',')) a);
select @hits;
다음 저장 프로 시저를 사용하여 값을 가져올 수 있습니다.
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
@c1
필요한 답변으로 설정 됩니다. table1
작동하도록 호출 된 기존 테이블이 필요 하고 하드 코드 된 델리 미터가 있으며 2 개월 전의 승인 된 답변처럼 인라인으로 사용할 수 없다는 점을 고려할 때 나머지 코드는 어떤 용도 로 사용됩니까?
Replace / Len 테스트는 귀엽지 만 매우 비효율적 일 수 있습니다 (특히 메모리 측면에서). 루프가있는 간단한 함수가 작업을 수행합니다.
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는 쿼리에 매우 비효율적입니다. 관련 테이블이어야합니다.