J'ai une colonne qui a des valeurs formatées comme a, b, c, d. Existe-t-il un moyen de compter le nombre de virgules dans cette valeur dans T-SQL?
La première façon de penser est de le faire indirectement en remplaçant la virgule par une chaîne vide et en comparant les longueurs.
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
Extension rapide de la réponse de cmsjr qui fonctionne pour les chaînes comportant plus de caractères.
CREATE FUNCTION dbo.CountOccurrencesOfString
(
@searchString nvarchar(max),
@searchTerm nvarchar(max)
)
RETURNS INT
AS
BEGIN
return (LEN(@searchString)-LEN(REPLACE(@searchString,@searchTerm,'')))/LEN(@searchTerm)
END
Usage:
SELECT * FROM MyTable
where dbo.CountOccurrencesOfString(MyColumn, 'MyString') = 1
Vous pouvez comparer la longueur de la chaîne avec celle où les virgules sont supprimées:
len(value) - len(replace(value,',',''))
La réponse de @csmjr pose problème dans certains cas.
Sa réponse était de faire ceci:
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
Cela fonctionne dans la plupart des scénarios, cependant, essayez d’exécuter ceci:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(@string) - LEN(REPLACE(@string, ',', ''))
Pour une raison quelconque, REPLACE supprime la virgule finale mais AUSSI l’espace situé juste avant (je ne sais pas pourquoi). Cela donne une valeur renvoyée de 5 alors que vous en attendiez 4. Voici une autre façon de procéder qui fonctionnera même dans ce scénario spécial:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(REPLACE(@string, ',', '**')) - LEN(@string)
Notez que vous n'avez pas besoin d'utiliser d'astérisques. Tout remplacement de deux caractères fera l'affaire. L'idée est de rallonger la chaîne d'un caractère pour chaque occurrence du caractère que vous comptez, puis de soustraire la longueur de l'original. C'est fondamentalement la méthode opposée de la réponse originale qui ne vient pas avec l'effet de coupe étrange.
En vous appuyant sur la solution de @ Andrew, vous obtiendrez de bien meilleures performances en utilisant une fonction de valeur table non procédurale et 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
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)
La réponse acceptée est correcte, L’étendre pour utiliser 2 caractères ou plus dans la sous-chaîne:
Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)
Je pense que Darrel Lee a une très bonne réponse. Remplacez CHARINDEX()
par PATINDEX()
, et vous pourrez également effectuer une recherche regex
faible le long d'une chaîne ...
Comme, disons que vous utilisez ceci pour @pattern
:
set @pattern='%[-.|!,'+char(9)+']%'
Pourquoi voudriez-vous peut-être faire quelque chose de fou comme ça?
Supposons que vous chargiez des chaînes de texte délimitées dans une table intermédiaire, où le champ contenant les données ressemble à varchar (8000) ou nvarchar (max) ...
Parfois, il est plus facile/plus rapide de faire ELT (Extract-Load-Transform) avec des données plutôt que ETL (Extract-Transform-Load), et une façon de faire est de charger les enregistrements délimités tels quels dans une table intermédiaire, en particulier si vous voudrez peut-être un moyen plus simple de voir les enregistrements exceptionnels plutôt que de les traiter dans le cadre d'un paquet SSIS ... mais c'est une guerre sainte pour un fil différent.
Utilisez ce code, il fonctionne parfaitement ... J'ai créé une fonction SQL qui accepte deux paramètres, le premier paramètre est la longue chaîne que nous voulons rechercher, et il peut accepter une longueur maximale de 1500 caractères (de Bien sûr, vous pouvez l'étendre ou même le changer en type de données texte) . Et le deuxième paramètre est la sous-chaîne que nous voulons calculer le nombre de son occurrence (sa longueur est jusqu'à 200 caractères, bien sûr, vous pouvez le changer pour de quoi avez-vous besoin? et la sortie est un entier, représente le nombre de fréquence ..... profitez-en.
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
Ce qui suit devrait faire l'affaire pour les recherches sur un ou plusieurs caractères:
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;
La fonction peut être simplifiée un peu en utilisant une table de nombres (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
);
J'écris enfin cette fonction qui devrait couvrir toutes les situations possibles, en ajoutant un préfixe et un suffixe de caractère à l'entrée. ce caractère est considéré différent de l'un des caractères contenus dans le paramètre de recherche, il ne peut donc pas affecter le résultat.
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
usage
select dbo.CountOccurrency('a,b,c,d ,', ',')
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'
En SQL 2017 ou supérieur, vous pouvez utiliser ceci:
declare @hits int = 0
set @hits = (select value from STRING_SPLIT('F609,4DFA,8499',','));
select count(@hits)
ce code T-SQL trouve et imprime toutes les occurrences du motif @p dans la phrase @s. vous pouvez faire n'importe quel traitement sur la phrase aprè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
le résultat est: 1 6 13 20
Si nous savons qu’il existe une limitation de LEN et d’espace, pourquoi ne pouvons-nous pas d'abord remplacer l’espace?.
len(replace(@string, ' ', '-')) - len(replace(replace(@string, ' ', '-'), ',', ''))
Declare @MainStr nvarchar(200)
Declare @SubStr nvarchar(10)
Set @MainStr = 'nikhildfdfdfuzxsznikhilweszxnikhil'
Set @SubStr = 'nikhil'
Select (Len(@MainStr) - Len(REPLACE(@MainStr,@SubStr,'')))/Len(@SubStr)