Подсчет буквенных символов в строковом поле в SQL Server - PullRequest
0 голосов
/ 07 мая 2019

Я использую SQL Server Management Studio v17.9.1.У меня есть столбец в таблице базы данных, которая содержит буквенно-цифровые строки.Мне нужно посчитать буквы в строке и составить таблицу агрегированных результатов, показывающих количество букв по количеству записей, у которых было такое количество букв в столбце.

Я также пытаюсь, если возможно, сделать список динамическим, чтобы строки в агрегированных результатах доходили до максимального количества букв в строке в столбце таблицы.

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

Спасибо за любую помощь.

Например: Таблица1

ID
----------
A00001
AB0001
AC123
CB00AD
1234AD

Сводные результаты:

No of letters          Count of records
-----------            -----------        
1                      1
2                      3
3                      0
4                      1

Ответы [ 5 ]

2 голосов
/ 07 мая 2019

Просто еще один вариант использования специальной таблицы подсчета

* ** 1003 тысяча два * Пример
Declare @YourTable Table ([ID] varchar(50))
Insert Into @YourTable Values 
 ('A00001')
,('AB0001')
,('AC123')
,('CB00AD')
,('1234AD')

Select Letters
      ,Cnt = count(*)
 From (    
        Select Letters = count(*)
         From  @YourTable A
         Join (
                Select Top (select max(len(ID)) from @YourTable) N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1
         ) B  on n<=len(ID)
         Where substring(ID,N,1) not like '[0-9]'
         Group By ID
       ) A
 Group By Letters

Returns

Letters Cnt
1       1
2       3
4       1
1 голос
/ 07 мая 2019

Используя NGrams8k , вы можете сделать это:

-- sample data
DECLARE @table TABLE(ID VARCHAR(30));
INSERT @table VALUES ('A00001'),('AB0001'),('AC123'),('CB00AD'),('1234AD');

-- Solution
WITH l(C) AS
(
  SELECT      Letters = SUM(PATINDEX('[A-Z]',ng.token))
  FROM        @table               AS t
  CROSS APPLY dbo.NGrams8k(t.ID,1) AS ng
  GROUP BY    t.ID
)
SELECT    Letters     = t.N, 
          RecordCount = COUNT(l.C)
FROM      (VALUES(1),(2),(3),(4)) AS t(N)
LEFT JOIN l ON t.N = l.C
GROUP BY  t.N;

Возвращает:

Letters     RecordCount
----------- -----------
1           1
2           3
3           0
4           1
1 голос
/ 07 мая 2019

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

CREATE FUNCTION dbo.CountChars(
    @String varchar(8000),
    @Pattern varchar(100)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
WITH 
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
    SELECT TOP( LEN(@String)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n
    FROM E4
)
SELECT COUNT(*) CharCount
FROM cteTally
WHERE SUBSTRING( @String, n, 1) LIKE @Pattern

GO

SELECT CharCount, COUNT(*)
FROM Table1
CROSS APPLY dbo.CountChars( ID, '[A-Za-Z]')
GROUP BY CharCount;
1 голос
/ 07 мая 2019

Тривиальный метод основан на замене

SELECT LEN(
REPLACE(
REPLACE(
REPLACE( 
REPLACE(
REPLACE(
REPLACE( 
REPLACE(
REPLACE(
REPLACE(
REPLACE(myColumn, '0', ''),
   '1',''),
   '2',''),
   '3',''),
   '4',''),
   '5',''),
   '6',''),
   '7',''),
   '8',''),
   '9','')
) num_char
from  your_table  
0 голосов
/ 07 мая 2019

Я знаю, производительность скалярной функции ... дает вам возможность убрать все не-альфа-символы из строки.Снимите len () с возврата.Другие комментарии верны, это не очень хорошая производительность.

Create Function dbo.AlphaOnly ( @inStr varchar(max) )
    Returns varchar(max)
as
    Begin
        Declare @curLoc int
        Set @curLoc = PatIndex('%[^A-Za-z]%', @inStr)
        While @curLoc > 0
            Begin
                Set @inStr = Stuff(@inStr,@curLoc,1,'')
                Set @curLoc = PatIndex('%[^A-Za-z]%', @inStr)
            End
        Return @inStr
    End
GO


...