मेरे पास एक कॉलम है जिसमें मानों को a, b, c, d जैसे स्वरूपित किया गया है। टी-एसक्यूएल में उस मूल्य में अल्पविराम की संख्या को गिनने का कोई तरीका है?
मेरे पास एक कॉलम है जिसमें मानों को a, b, c, d जैसे स्वरूपित किया गया है। टी-एसक्यूएल में उस मूल्य में अल्पविराम की संख्या को गिनने का कोई तरीका है?
जवाबों:
पहला तरीका जो मन में आता है वह है अप्रत्यक्ष रूप से अल्पविराम की जगह खाली स्ट्रिंग और लंबाई की तुलना करके।
Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))
LTRIMस्ट्रिंग के चारों ओर लपेट क्यों नहीं इस प्रकार है SELECT LEN(RTRIM(@string)) - LEN(REPLACE(RTRIM(@string), ',', '')):?
Cmsjr के उत्तर का त्वरित विस्तार जो अधिक वर्ण से अधिक तार के लिए काम करता है।
CREATE FUNCTION dbo.CountOccurrencesOfString
(
@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.CountOccurrencesOfString(MyColumn, 'MyString') = 1
dbo.CountOccurancesOfString( 'blah ,', ',')देगा इसलिए 1 के बजाय 2 वापस आ dbo.CountOccurancesOfString( 'hello world', ' ')जाएंगे और शून्य से विभाजित होने में विफल रहेंगे।
DATALENGTH()/2गैर-स्पष्ट चार आकारों के कारण भी मुश्किल है। सरल और सटीक तरीके के लिए stackoverflow.com/a/11080074/1094048 पर देखें ।
@ एंड्रयू समाधान पर बिल्डिंग, आपको एक गैर-प्रक्रियात्मक तालिका-मूल्यवान-फ़ंक्शन और CROSS APPLYY का उपयोग करके बहुत बेहतर प्रदर्शन मिलेगा:
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
@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, ',', ''))
किसी कारण से, REPLACE को अंतिम अल्पविराम से छुटकारा मिल जाता है, लेकिन इसके ठीक पहले वाला स्थान भी (निश्चित नहीं है कि क्यों)। जब आप अपेक्षा करेंगे तो यह 5 के लौटाए गए मूल्य का परिणाम है। यहाँ ऐसा करने का एक और तरीका है जो इस विशेष परिदृश्य में भी काम करेगा:
DECLARE @string VARCHAR(1000)
SET @string = 'a,b,c,d ,'
SELECT LEN(REPLACE(@string, ',', '**')) - LEN(@string)
ध्यान दें कि आपको तारांकन का उपयोग करने की आवश्यकता नहीं है। कोई भी दो-चरित्र प्रतिस्थापन करेगा। विचार यह है कि आप जिस चरित्र की गिनती कर रहे हैं उसके प्रत्येक उदाहरण के लिए स्ट्रिंग को एक वर्ण से लंबा करते हैं, फिर मूल की लंबाई घटाते हैं। यह मूल रूप से मूल उत्तर की विपरीत विधि है जो अजीब ट्रिमिंग साइड-इफेक्ट के साथ नहीं आती है।
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)
स्वीकृत उत्तर सही है, विकल्प में 2 या अधिक वर्ण का उपयोग करने के लिए इसे विस्तारित करना:
Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)
डारेल ली मुझे लगता है कि एक बहुत अच्छा जवाब है। के CHARINDEX()साथ बदलें PATINDEX(), और आप कुछ कमजोर कर सकते हैंregex एक स्ट्रिंग के साथ खोज भी ...
जैसे, आप इसके लिए इसका उपयोग करते हैं @pattern:
set @pattern='%[-.|!,'+char(9)+']%'
आप इस तरह से कुछ पागल क्यों करना चाहेंगे?
मान लें कि आप सीमांकित पाठ स्ट्रिंग्स को एक मेज़िंग तालिका में लोड कर रहे हैं, जहाँ डेटा रखने वाला क्षेत्र कुछ varchar (8000) या nvarchar (अधिकतम) की तरह है ...
कभी-कभी ईटीएल (एक्सट्रैक्ट-ट्रांसफ़ॉर्म-लोड) के बजाय डेटा के साथ ईएलटी (एक्सट्रैक्ट-लोड-ट्रांसफ़ॉर्म) करना आसान / तेज़ होता है, और ऐसा करने का एक तरीका सीमांकित रिकॉर्ड को लोड करना है, जैसे कि एक स्टेजिंग टेबल में, खासकर यदि आप SSIS पैकेज के एक हिस्से के रूप में उनके साथ असाधारण रिकॉर्ड देखने के लिए एक सरल तरीका चाहते हैं ... लेकिन यह एक अलग धागे के लिए एक पवित्र युद्ध है।
निम्नलिखित को एकल वर्ण और एकाधिक वर्ण खोज दोनों के लिए चाल करनी चाहिए:
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
);
इस कोड का उपयोग करें, यह पूरी तरह से काम कर रहा है। मैंने एक sql फ़ंक्शन बनाया है जो दो मापदंडों को स्वीकार करता है, पहला परम लम्बी स्ट्रिंग है जिसे हम इसमें खोजना चाहते हैं, और यह स्ट्रिंग की लंबाई 1500 वर्ण तक स्वीकार कर सकता है (बेशक आप इसे विस्तारित कर सकते हैं या इसे पाठ डेटाटाइप में भी बदल सकते हैं )। और दूसरा पैरामीटर यह विकल्प है कि हम इसकी संख्या की गणना करना चाहते हैं (इसकी लंबाई 200 वर्ण तक है, निश्चित रूप से आप इसे अपनी आवश्यकता के अनुसार बदल सकते हैं)। और आउटपुट एक पूर्णांक है, आवृत्ति की संख्या का प्रतिनिधित्व करता है ..... इसका आनंद लें।
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
मैं अंत में इस फ़ंक्शन को लिखता हूं जो इनपुट में एक उपसर्ग और प्रत्यय जोड़कर सभी संभावित स्थितियों को कवर करना चाहिए। इस char का मूल्यांकन खोज पैरामीटर में किसी भी char conteined के भिन्न होने के लिए किया जाता है, इसलिए यह परिणाम को प्रभावित नहीं कर सकता है।
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
प्रयोग
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)
SQL 2017 या उच्चतर में, आप इसका उपयोग कर सकते हैं:
declare @hits int = 0
set @hits = (select value from STRING_SPLIT('F609,4DFA,8499',','));
select count(@hits)
यह T-SQL कोड पैटर्न @p के सभी आवृत्तियों को ढूँढता है और प्रिंट करता है @ 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
परिणाम है: 1 6 13 20
SQL सर्वर 2017 के लिए
declare @hits int = 0;
set @hits = (select count(*) from (select value from STRING_SPLIT('F609,4DFA,8499',',')) a);
select @hits;
आप मूल्यों को लाने के लिए निम्न संग्रहीत कार्यविधि का उपयोग कर सकते हैं।
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उस उत्तर पर सेट होती है, जिसकी उसे आवश्यकता होती है। बाकी कोड क्या उपयोग है, इस पर विचार करते हुए कि इसे काम करने के लिए एक पूर्व मौजूदा तालिका की आवश्यकता है table1, जिसमें एक कठोर कोडित परिधि है, और दो महीने पहले से स्वीकृत उत्तर की तरह इनलाइन का उपयोग नहीं किया जा सकता है?
बदलें / लेन परीक्षण प्यारा है, लेकिन शायद बहुत अक्षम (विशेष रूप से स्मृति के संदर्भ में)। लूप के साथ एक सरल कार्य काम करेगा।
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
शायद आपको उस तरह से डेटा स्टोर नहीं करना चाहिए। एक क्षेत्र में कभी भी अल्पविराम सीमांकित सूची को संग्रहीत करना एक बुरा अभ्यास है। IT क्वेरी करने के लिए बहुत अक्षम है। यह संबंधित तालिका होनी चाहिए।