Как вы подсчитываете количество вхождений определенной подстроки в SQL varchar? - PullRequest
131 голосов
/ 10 апреля 2009

У меня есть столбец, значения которого отформатированы как a, b, c, d. Есть ли способ подсчитать количество запятых в этом значении в T-SQL?

Ответы [ 19 ]

0 голосов
/ 08 марта 2019
Declare @MainStr nvarchar(200)
Declare @SubStr nvarchar(10)
Set @MainStr = 'nikhildfdfdfuzxsznikhilweszxnikhil'
Set @SubStr = 'nikhil'
Select (Len(@MainStr) - Len(REPLACE(@MainStr,@SubStr,'')))/Len(@SubStr)
0 голосов
/ 26 сентября 2018

Наконец, я пишу эту функцию, которая должна охватывать все возможные ситуации, добавляя префикс 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 ,', ',')
0 голосов
/ 07 августа 2018

Используйте этот код, он работает отлично. Я создал функцию sql, которая принимает два параметра, первый параметр - это длинная строка, которую мы хотим найти в ней, и она может принимать длину строки до 1500 символов (конечно, вы можете расширить ее или даже изменить на тип данных text). ). А вторым параметром является подстрока, по которой мы хотим вычислить номер ее вхождения (его длина до 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
0 голосов
/ 02 марта 2018

Следующие действия должны помочь при поиске как одного, так и нескольких символов:

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
          );
0 голосов
/ 10 апреля 2009

Возможно, вам не следует хранить данные таким образом. Не рекомендуется хранить список с разделителями-запятыми в поле. Это очень неэффективно для запросов. Это должна быть связанная таблица.

0 голосов
/ 16 июля 2014

Даррел Ли: Думаю, у меня довольно хороший ответ. Замените CHARINDEX() на PATINDEX(), и вы также можете выполнить слабый regex поиск по строке ...

Как, скажем, вы используете это для @pattern:

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

Зачем вам хотеть делать что-то сумасшедшее, как это?

Допустим, вы загружаете текстовые строки с разделителями в промежуточную таблицу, где поле, содержащее данные, является чем-то вроде varchar (8000) или nvarchar (max) ...

Иногда проще / быстрее выполнять ELT (Extract-Load-Transform) с данными, а не ETL (Extract-Transform-Load), и один из способов сделать это - загрузить записи с разделителями как есть в промежуточную таблицу особенно если вам нужен более простой способ просмотра исключительных записей, а не обработки их как части пакета служб SSIS ... но это священная война для другого потока.

0 голосов
/ 11 февраля 2014

Тест 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
0 голосов
/ 08 июня 2012

Вы можете использовать следующую хранимую процедуру для извлечения значений.

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
0 голосов
/ 12 апреля 2009
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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...