Saya memiliki kolom yang memiliki nilai yang diformat seperti a, b, c, d. Apakah ada cara untuk menghitung jumlah koma dalam nilai itu di T-SQL?
Saya memiliki kolom yang memiliki nilai yang diformat seperti a, b, c, d. Apakah ada cara untuk menghitung jumlah koma dalam nilai itu di T-SQL?
Jawaban:
Cara pertama yang terlintas dalam pikiran adalah melakukannya secara tidak langsung dengan mengganti koma dengan string kosong dan membandingkan panjangnya
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
LTRIM
sekitar string sebagai berikut: SELECT LEN(RTRIM(@string)) - LEN(REPLACE(RTRIM(@string), ',', ''))
?
Perpanjangan cepat jawaban cmsjr yang berfungsi untuk string lebih dari lebih banyak karakter.
CREATE FUNCTION dbo.CountOccurrencesOfString
(
@searchString nvarchar(max),
@searchTerm nvarchar(max)
)
RETURNS INT
AS
BEGIN
return (LEN(@searchString)-LEN(REPLACE(@searchString,@searchTerm,'')))/LEN(@searchTerm)
END
Pemakaian:
SELECT * FROM MyTable
where dbo.CountOccurrencesOfString(MyColumn, 'MyString') = 1
dbo.CountOccurancesOfString( 'blah ,', ',')
akan mengembalikan 2 bukannya 1 dan dbo.CountOccurancesOfString( 'hello world', ' ')
akan gagal dengan membagi dengan nol.
DATALENGTH()/2
juga rumit karena ukuran char tidak jelas. Lihatlah stackoverflow.com/a/11080074/1094048 untuk cara yang sederhana dan akurat.
Dengan menggunakan solusi @ Andrew, Anda akan mendapatkan kinerja yang jauh lebih baik menggunakan fungsi bernilai tabel non-prosedural dan CROSS BERLAKU:
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
Jawaban oleh @csmjr memiliki masalah dalam beberapa kasus.
Jawabannya adalah melakukan ini:
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
Ini berfungsi di sebagian besar skenario, namun, coba jalankan ini:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(@string) - LEN(REPLACE(@string, ',', ''))
Untuk beberapa alasan, REPLACE menghilangkan koma terakhir tetapi JUGA ruang sebelum itu (tidak yakin mengapa). Ini menghasilkan nilai 5 yang dikembalikan saat Anda mengharapkan 4. Berikut adalah cara lain untuk melakukan ini yang akan berfungsi bahkan dalam skenario khusus ini:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(REPLACE(@string, ',', '**')) - LEN(@string)
Perhatikan bahwa Anda tidak perlu menggunakan tanda bintang. Penggantian dua karakter apa pun akan dilakukan. Idenya adalah Anda memperpanjang string dengan satu karakter untuk setiap instance karakter yang Anda hitung, lalu kurangi panjang aslinya. Ini pada dasarnya metode yang berlawanan dari jawaban asli yang tidak datang dengan efek samping pemangkasan yang aneh.
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)
Jawaban yang diterima benar, memperluasnya menggunakan 2 atau lebih karakter dalam substring:
Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)
Saya kira Darrel Lee punya jawaban yang cukup bagus. Ganti CHARINDEX()
dengan PATINDEX()
, dan Anda dapat melakukan regex
pencarian yang lemah di sepanjang string, juga ...
Seperti, katakan Anda menggunakan ini untuk @pattern
:
set @pattern='%[-.|!,'+char(9)+']%'
Mengapa Anda mungkin ingin melakukan sesuatu yang gila seperti ini?
Katakanlah Anda sedang memuat string teks terbatas ke tabel pementasan, di mana bidang yang menyimpan data adalah sesuatu seperti varchar (8000) atau nvarchar (maks) ...
Terkadang lebih mudah / lebih cepat untuk melakukan ELT (Extract-Load-Transform) dengan data daripada ETL (Extract-Transform-Load), dan salah satu cara untuk melakukan ini adalah dengan memuat catatan yang dibatasi seperti apa adanya ke dalam tabel pementasan, terutama jika Anda mungkin menginginkan cara yang lebih sederhana untuk melihat catatan yang luar biasa daripada berurusan dengan mereka sebagai bagian dari paket SSIS ... tapi itu perang suci untuk utas yang berbeda.
Hal-hal berikut harus melakukan trik untuk pencarian karakter tunggal dan banyak karakter:
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;
Fungsi ini dapat disederhanakan sedikit menggunakan tabel angka (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
);
Gunakan kode ini, ini berfungsi dengan baik. Saya telah membuat fungsi sql yang menerima dua parameter, param pertama adalah string panjang yang ingin kita cari di dalamnya, dan dapat menerima panjang string hingga 1500 karakter (tentu saja Anda dapat memperluas atau bahkan mengubahnya ke datatype teks ). Dan parameter kedua adalah substring yang ingin kita hitung jumlah kemunculannya (panjangnya hingga 200 karakter, tentu saja Anda dapat mengubahnya sesuai dengan kebutuhan Anda). dan output adalah bilangan bulat, mewakili jumlah frekuensi ..... nikmatilah.
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
Saya akhirnya menulis fungsi ini yang harus mencakup semua situasi yang mungkin, menambahkan awalan char dan akhiran ke input. arang ini dievaluasi berbeda dengan arang yang terdapat pada parameter pencarian, sehingga tidak dapat mempengaruhi hasilnya.
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
pemakaian
select dbo.CountOccurrency('a,b,c,d ,', ',')
Declare @MainStr nvarchar(200)
Declare @SubStr nvarchar(10)
Set @MainStr = 'nikhildfdfdfuzxsznikhilweszxnikhil'
Set @SubStr = 'nikhil'
Select (Len(@MainStr) - Len(REPLACE(@MainStr,@SubStr,'')))/Len(@SubStr)
Di SQL 2017 atau lebih tinggi, Anda dapat menggunakan ini:
declare @hits int = 0
set @hits = (select value from STRING_SPLIT('F609,4DFA,8499',','));
select count(@hits)
kode T-SQL ini menemukan dan mencetak semua kemunculan pola @p dalam kalimat @s. Anda dapat melakukan pemrosesan pada kalimat setelahnya.
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
hasilnya adalah: 1 6 13 20
untuk SQL Server 2017
declare @hits int = 0;
set @hits = (select count(*) from (select value from STRING_SPLIT('F609,4DFA,8499',',')) a);
select @hits;
Anda dapat menggunakan prosedur tersimpan berikut untuk mengambil, nilai.
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 complainid=@cid;
while (@c<=@c1)
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 @c=@c+1
end
@c1
ke jawaban yang dia butuhkan. Apa gunanya sisa kode, mengingat perlu tabel yang sudah ada sebelumnya dipanggil table1
untuk bekerja, memiliki delimeter kode keras, dan tidak dapat digunakan sebaris seperti jawaban yang diterima dari dua bulan sebelumnya?
Tes Replace / Len lucu, tetapi mungkin sangat tidak efisien (terutama dalam hal memori). Fungsi sederhana dengan loop akan melakukan pekerjaan itu.
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
Mungkin Anda sebaiknya tidak menyimpan data seperti itu. Merupakan praktik yang buruk untuk pernah menyimpan daftar yang dibatasi koma di bidang. TI sangat tidak efisien untuk query. Ini harus berupa tabel terkait.