Как посчитать количество вхождений символов в строке в sql?

#sql-server

Вопрос:

Мне нужно количество всех символов, которые появляются в word. Например, если я напишу Питер, я хочу, чтобы результат был таким

 P 1
e 2
t 1
e 2
r 1
 

Любая помощь будет признательна.

Комментарии:

1. Почему вы хотите сделать это в SQL Server ? Это не имеет никакого отношения к SQL Server

Ответ №1:

Если открыт для ТВФ. Будучи функцией с табличным значением, она может использоваться в CROSS APPLY

Пример

 Select *
      ,Cnt = sum(1) over (partition by RetVal) 
 From  [dbo].[tvf-Str-Parse-Char]('Peter') 
 Order By RetSeq
 

ВОЗВРАТ

 RetSeq  RetVal  Cnt
1       P       1
2       e       2
3       t       1
4       e       2
5       r       1
 

Функция, если это интересно

 CREATE FUNCTION [dbo].[tvf-Str-Parse-Char] (@String varchar(max))
Returns Table
As
Return (
    with   cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From cte1 a,cte1 b,cte1 c,cte1 d,cte1 e,cte1 f)

    Select RetSeq=N
          ,RetVal=Substring(@String,N,1) 
     From  cte2
) 
--Max 1 Million Observations
--Select * from [dbo].[tvf-Str-Parse-Char]('this is a string') 
 

Комментарии:

1. Почему DATALENGTH и почему нет LEN ?

2. @Charlieface Конечные пробелы в строке. Лен будет игнорировать, в то время как длина данных будет их считать

3. @Charlieface извините .. только 1 кофе этим утром. dbfiddle.uk/…

Ответ №2:

То, что Джон опубликовал выше, известно как функция Unigram; ОНА же N-Грамм размера 1. Для функции N-граммов, которая поддерживает токены любого размера, см.: Nasty Fast N-Граммы, часть 1. Существует версия 8K и VARCHAR(MAX). Использование ngrams8k:

 DECLARE @string VARCHAR(100) = 'Peter';

SELECT   ng.Position, ng.Token, COUNT(ng.Token) OVER (PARTITION BY ng.Token) AS cnt
FROM     dbo.ngrams8k(@string,1) AS ng
ORDER BY ng.Position;
 

ВОЗВРАТ:

 Position    Token      cnt
----------- ---------- -----------
1           P          1
2           e          2
3           t          1
4           e          2
5           r          1
 

Обратите внимание, что вторым параметром в функции является размер токена, вот основной пример того, что вы можете сделать помимо юниграмм. Допустим, мы хотели найти строку для всех экземпляров определенной подстроки, «ABC» в этом примере:

 DECLARE 
  @string VARCHAR(8000) = '123ABC xxx yyy ABCDEABC...ABB',
  @searchFor VARCHAR(100) = 'ABC';

SELECT ng.* 
FROM   dbo.Ngrams8k(@string,LEN(@searchFor)) AS ng
WHERE  ng.Token = @searchFor;
 

ВОЗВРАТ:

 position    token
----------- -------
4           ABC
16          ABC
21          ABC