У меня есть столбец, который имеет значения, отформатированные как a, b, c, d. Есть ли способ подсчитать количество запятых в этом значении в T-SQL?Как вы рассчитываете количество вхождений определенной подстроки в SQL varchar?
ответ
Первый способ, который приходит на ум, чтобы сделать это косвенно, заменив запятую с пустой строкой и сравнения длин
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
Вы можете сравнить длину строки с одной, где запятые удаляются :
len(value) - len(replace(value,',',''))
Возможно, вы не должны хранить данные таким образом. Плохая практика всегда хранить список с разделителями-запятыми в поле. Это очень неэффективно для запросов. Это должна быть связанная таблица.
+1 за это. Это то, что я обычно начинаю с того, когда кто-то использует данные, разделенные запятыми, в поле. – Guffa
Часть цели этого вопроса заключалась в том, чтобы использовать существующие данные и разделить их соответствующим образом. –
Некоторые из нас получают устаревшие базы данных, где это было сделано, и мы ничего не можем с этим поделать. – eddieroger
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'
Быстрое расширение ответа cmsjr, которое работает для строк более чем символа.
CREATE FUNCTION dbo.CountOccurancesOfString
(
@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.CountOccurancesOfString(MyColumn, 'MyString') = 1
Небольшое улучшение было бы использовать DATALENGTH()/2 вместо LEN(). LEN игнорирует любые конечные пробелы, поэтому 'dbo.CountOccurancesOfString ('blah,', ',')' вернет 2 вместо 1 и 'dbo.CountOccurancesOfString ('hello world', '')' будет терпеть неудачу с делением на ноль. – Rory
Комментарий Рори очень полезен. Я обнаружил, что могу просто заменить LEN DATALENGTH в функции Эндрю и получить желаемый результат. Кажется, что разделение на 2 не обязательно с помощью математики. –
@AndrewBarrett: Что добавить, когда несколько строк имеют одинаковую длину? – user2284570
Вы можете использовать следующую хранимую процедуру для выборки, значения.
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 [email protected];
while (@c<[email protected])
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 @[email protected]+1
end
строка 4 этой хранимой процедуры устанавливает '@ c1' ответ, который он требует. Какая польза от остальной части кода, учитывая, что для работы требуется предварительно существующая таблица, называемая «table1», имеет жесткий кодированный делитель и не может использоваться как встроенный, как принятый ответ за два месяца до этого? –
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)
Заменить/испытание 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
Через любой стол заметного размера, используя процедурные функции, _far_ более неэффективно –
Хорошая точка. Является ли построенный вызов Лен намного быстрее, чем функция, используемая функцией? –
В большом масштабе записей, да. Хотя, конечно, вам придется протестировать большой набор записей с большими строками. Никогда не пишите ничего процедурного в SQL, если вы можете его избежать (т. Е. Петли) –
Darrel Lee Я думаю, что есть довольно хороший ответ. Заменить CHARINDEX()
с PATINDEX()
, и вы можете сделать некоторые слабые regex
поиск по струне, тоже ...
Мол, что вы используете это для @pattern
:
set @pattern='%[-.|!,'+char(9)+']%'
Почему вы, возможно, хотите сделать что-то сумасшедшее как это?
Допустим, вы загружаются с разделителями строк текста в промежуточную таблицу, где поле, содержащее данные, что-то вроде VARCHAR (8000) или NVARCHAR (макс) ...
Иногда бывает проще/быстрее сделать ELT (Extract-Load-Transform) с данными, а не ETL (Extract-Transform-Load), и один из способов сделать это - загрузить разделительные записи как есть в промежуточную таблицу, особенно если вам может понадобиться более простой способ видеть исключительные записи, а не рассматривать их как часть пакета SSIS ... но это священная война для другого потока.
У ответа @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, ',', ''))
По какой-то причине, ЗАМЕНА избавляется от окончательной запятой, но и пространство перед ним (не знаю, почему). Это приводит к возвращаемому значению 5, когда вы ожидаете 4. Вот еще один способ сделать это, который будет работать даже в этом особом случае:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(REPLACE(@string, ',', '**')) - LEN(@string)
Обратите внимание, что вам не нужно использовать звездочку. Любая двухсимвольная замена будет выполнена. Идея состоит в том, что вы удлиняете строку по одному символу для каждого экземпляра персонажа, который вы подсчитываете, а затем вычитаете длину оригинала. Это в основном противоположный метод первоначального ответа, который не приходит со странным побочным эффектом обрезки.
«По какой-то причине REPLACE избавляется от последней запятой, но ТАКЖЕ пространство перед ним (не знаю, почему)». REPLACE не избавляется от последней запятой и пространства перед ним, это фактически функция LEN, которая игнорирует пустое пространство, возникающее в конце строки из-за этого пространства. –
Опираясь на @ решения Эндрю, вы получите гораздо более высокую производительность, используя непроцедурный табличное значение-функции и 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
Я использую эту функцию во многих моих устаревших базах данных, она очень помогает многим старым и ненастроенным базам данных. Экономит много времени и очень быстро работает даже на больших наборах данных. – Caimen
Принято ответ правильный, распространив его использовать 2 или более символов в подстроке:
Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)
следующая следует сделать трюк как для одиночного символа и нескольких запросов символов:
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
);
- 1. SQL: Как вы рассчитываете количество уникальных записей?
- 2. Как вы рассчитываете количество определенной цифры с помощью Схемы?
- 3. Найти количество вхождений подстроки
- 4. как вы рассчитываете количество цифр в int?
- 5. Записать количество вхождений определенной подстроки в VECTOR строк
- 6. Как вычислить количество вхождений символа в varchar в одном SQL?
- 7. Найти общее количество вхождений подстроки
- 8. Как вы рассчитываете на вариации подстроки в строковом модуле?
- 9. SQL - количество вхождений слова
- 10. Swift :: Количество вхождений подстроки в строке
- 11. вхождений подстроки
- 12. Как вы рассчитываете количество элементов в списке в FileMaker
- 13. Как вы рассчитываете количество документов в коллекции MongoDB в узле?
- 14. Как вы рассчитываете количество определенного слова в абзаце, используя C#
- 15. Как вы рассчитываете количество последовательных дат в таблице?
- 16. Как вы рассчитываете количество целых чисел в файле? (C++)
- 17. Как вы рассчитываете наибольшее количество повторений в списке?
- 18. Как заменить несколько вхождений подстроки в C#
- 19. MySQL - подсчитайте количество вхождений по шаблону в поле VARCHAR?
- 20. Число вхождений подстроки в строке
- 21. Как вы рассчитываете количество «уровней» потомков узла Нокогири?
- 22. Как вы рассчитываете количество недель между двумя датами?
- 23. Как вы рассчитываете количество возможностей, связанных с контактом?
- 24. Как вы рассчитываете связанные строки в запросе
- 25. Как вы рассчитываете количество задач в расписании в день в SQL Server?
- 26. Как вы рассчитываете дату истечения срока действия в SQL Server?
- 27. Как проверить количество вхождений определенной строки в другую строку?
- 28. Как вы рассчитываете строки в приращении?
- 29. Подсчет вхождений подстроки в строке []
- 30. MySQL - Количество последовательных вхождений
Это отвечает на вопрос, как написано в тексте, но не как написано в названии. Чтобы сделать работу более чем одним персонажем, просто нужно добавить/len (searchterm) вокруг вещи. Написал ответ в случае, если это полезно для кого-то. –
Кто-то указал мне, что это не всегда работает так, как ожидалось. Рассмотрим следующее: SELECT LEN ('a, b, c, d,') - LEN (ЗАМЕНИТЬ ('a, b, c, d,', ',', '')) По причинам, Пока еще не понятно, пространство между d и последним столбцом заставляет это возвращать 5 вместо 4. Я отправлю еще один ответ, который исправляет это, в случае, если это полезно кому угодно. – bubbleking
Возможно, использование DATALENGTH вместо LEN было бы лучше, потому что LEN возвращает размер обрезанной строки. – rodrigocl