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

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

Ответы [ 19 ]

212 голосов
/ 10 апреля 2009

Первый способ, который приходит на ум, - сделать это косвенно, заменив запятую пустой строкой и сравнив длины

Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
62 голосов
/ 25 мая 2010

Быстрое расширение ответа 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
21 голосов
/ 10 апреля 2009

Вы можете сравнить длину строки с той, в которой запятые удалены:

len(value) - len(replace(value,',',''))
6 голосов
/ 30 апреля 2015

В некоторых случаях ответ @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 избавляется от последней запятой, но ТАКЖЕ и пробел непосредственно перед ней (не знаю почему). Это дает возвращаемое значение 5, когда вы ожидаете 4. Вот другой способ сделать это, который будет работать даже в этом специальном сценарии:

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

Обратите внимание, что вам не нужно использовать звездочки. Подойдет любая двухсимвольная замена. Идея состоит в том, что вы удлиняете строку на один символ для каждого экземпляра считаемого символа, а затем вычитаете длину оригинала. Это в основном противоположный метод первоначального ответа, который не сопровождается странным побочным эффектом обрезки.

5 голосов
/ 04 февраля 2016

Опираясь на решение @ 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
2 голосов
/ 04 февраля 2013
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)
1 голос
/ 26 июня 2018

Если мы знаем, что есть ограничение на LEN и пространство, почему мы не можем сначала заменить пространство? Тогда мы знаем, что нет места, чтобы запутать ЛЕН.

len(replace(@string, ' ', '-')) - len(replace(replace(@string, ' ', '-'), ',', ''))
1 голос
/ 23 ноября 2017

Принятый ответ правильный, расширяя его, чтобы использовать 2 или более символа в подстроке:

Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)
0 голосов
/ 27 марта 2019

этот код T-SQL находит и печатает все вхождения шаблона @p в предложении @s. Вы можете выполнить любую обработку предложения позже.

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

0 голосов
/ 19 марта 2019

В SQL 2017 или выше вы можете использовать это:

declare @hits int = 0
set @hits = (select value from STRING_SPLIT('F609,4DFA,8499',','));
select count(@hits)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...