এসকিউএল বারচারে কোনও নির্দিষ্ট স্ট্রিংয়ের সংঘটনগুলির সংখ্যা আপনি কীভাবে গণনা করবেন?


150

আমার কাছে একটি কলাম রয়েছে যার মান, a, b, c, d এর মতো ফর্ম্যাট রয়েছে। টি-এসকিউএলে সেই মানটিতে কমাগুলির সংখ্যা গণনা করার কোনও উপায় আছে?

উত্তর:


245

প্রথম যে বিষয়টি মনে আসে তা হ'ল খালি স্ট্রিং দিয়ে কমা প্রতিস্থাপন করে এবং দৈর্ঘ্যের তুলনা করে পরোক্ষভাবে এটি করা

Declare @string varchar(1000)
Set @string = 'a,b,c,d'
select len(@string) - len(replace(@string, ',', ''))

13
যা পাঠ্যে লিখিতভাবে প্রশ্নের উত্তর দেয়, তবে শিরোনামে লেখা হয় না। এটি একাধিক চরিত্রের জন্য কাজ করার জন্য, কেবল জিনিসটির চারপাশে একটি / লেন (সার্চটার্ম) যুক্ত করা দরকার। একটি উত্তর পোস্ট করুন যদি এটি কারওর জন্য দরকারী।
অ্যান্ড্রু ব্যারেট

কেউ আমাকে ইঙ্গিত করেছিলেন যে এটি সর্বদা প্রত্যাশা মতো কাজ করে না। নিম্নলিখিতগুলি বিবেচনা করুন: লেন নির্বাচন করুন ('a, b, c, d,') - LEN (REPLACE ('a, b, c, d,', ',', '')) কারণে আমি এখনও বুঝতে পারি না , ডি এবং চূড়ান্ত কলামের মধ্যবর্তী স্থানের কারণে এটি 4 এর পরিবর্তে 5 ফিরে আসবে I
বুবলিং

5
এর পরিবর্তে LENL DENLEGGTH ব্যবহার করা আরও ভাল হবে কারণ LEN স্ট্রিংয়ের আকারটি ছাঁটাই করে দেয় returns
রডগ্রোকল

2
ডেটালেগথ () / 2 অ-সুস্পষ্ট চর মাপের কারণেও জটিল। স্ট্রিংয়ের দৈর্ঘ্য পাওয়ার সহজ এবং সঠিক উপায়ের জন্য stackoverflow.com/a/11080074/1094048 দেখুন।
pkuderov

@rodrigocl কেন একটি মোড়ানো না LTRIMস্ট্রিংয়ের নিম্নরূপ: SELECT LEN(RTRIM(@string)) - LEN(REPLACE(RTRIM(@string), ',', ''))?
অ্যালেক্স বেলো

67

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

16
সামান্য উন্নতি হবে LEN () এর পরিবর্তে DATLENGTH () / 2 ব্যবহার করা। LEN কোনও পেছনের সাদা স্থান উপেক্ষা করবে তাই dbo.CountOccurancesOfString( 'blah ,', ',')1 এর পরিবর্তে 2 ফিরে আসবে এবং dbo.CountOccurancesOfString( 'hello world', ' ')শূন্য দ্বারা বিভাজনে ব্যর্থ হবে।
ররি

5
ররির মন্তব্য সহায়ক। আমি দেখতে পেয়েছি যে আমি কেবল অ্যান্ড্রুয়ের ফাংশনে ডেএনএলএনটিএইচটির সাথে এলইএন প্রতিস্থাপন করতে এবং পছন্দসই ফলাফল পেতে পারি। দেখে মনে হচ্ছে গণিতটি যেভাবে কাজ করবে তার সাথে 2 দিয়ে বিভাজক করা জরুরী নয়।
গারল্যান্ড পোপ 15

@ অ্যান্ড্রুবারেট: বেশ কয়েকটি স্ট্রিংয়ের দৈর্ঘ্য একই হলে কী হবে?
ব্যবহারকারী 2284570

2
DATALENGTH()/2অ-সুস্পষ্ট চর মাপের কারণে এটিও জটিল। সহজ এবং নির্ভুল উপায়ে stackoverflow.com/a/11080074/1094048 দেখুন ।
pkuderov

26

আপনি কমাগুলি অপসারণ করা হয়েছে তার সাথে স্ট্রিংয়ের দৈর্ঘ্যের তুলনা করতে পারেন:

len(value) - len(replace(value,',',''))

8

@ অ্যান্ড্রুয়ের সমাধানের উপর ভিত্তি করে, আপনি একটি নন-প্রসেসরিজাল টেবিল-মূল্যবান-ফাংশন এবং ক্রস অ্যাপ্লাই ব্যবহার করে আরও ভাল পারফরম্যান্স পাবেন:

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

আমি আমার বহু উত্তরাধিকারের ডেটাবেজে এই একই ফাংশনটি ব্যবহার করি, এটি প্রচুর পুরানো এবং অযথাই নকশাকৃত ডেটাবেসগুলির সাথে একটি দুর্দান্ত কাজ করে। অনেক সময় সাশ্রয় করে এবং বড় ডেটা সেটগুলিতেও খুব দ্রুত।
কেইমন

6

@ সিএসএমজেআরের উত্তরের কিছু ক্ষেত্রে সমস্যা আছে।

তার উত্তর ছিল এটি:

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)

নোট করুন যে আপনাকে অ্যাসিরিস্টস ব্যবহার করার দরকার নেই। যে কোনও দ্বি-চরিত্রের প্রতিস্থাপন তা করবে। ধারণাটি হ'ল আপনি যে চরিত্রটি গণনা করছেন তার প্রতিটি উদাহরণের জন্য আপনি একটি অক্ষর দ্বারা স্ট্রিং দীর্ঘ করুন, তারপরে মূলের দৈর্ঘ্যটি বিয়োগ করুন। এটি মূলত আসল উত্তরের বিপরীত পদ্ধতি যা অদ্ভুত ট্রিমিং পার্শ্ব-প্রতিক্রিয়া নিয়ে আসে না।


5
"কোনও কারণে, প্রতিস্থাপন চূড়ান্ত কমা থেকে মুক্তি পেয়েছে তবে এর ঠিক আগে স্থানটি (ঠিক আছে কেন তা নিশ্চিত নয়)।" প্রতিস্থাপনটি শেষ কমা এবং এর আগে স্থান থেকে মুক্তি পাচ্ছে না, এটি আসলে লেন ফাংশন যা সেই স্থানটির কারণে স্ট্রিংয়ের শেষের ফলে হোয়াইট-স্পেসকে অগ্রাহ্য করে।
ইমরানুল্লাহ খান

2
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)

এটি প্রকৃত গণনাটির তুলনায় 1 টি কম দেয়
ইন্টিগ্রেটার

1

গৃহীত উত্তর সঠিক, এটি স্ট্রিংগুলিতে 2 বা ততোধিক অক্ষর ব্যবহার করতে প্রসারিত:

Declare @string varchar(1000)
Set @string = 'aa,bb,cc,dd'
Set @substring = 'aa'
select (len(@string) - len(replace(@string, @substring, '')))/len(@substring)

1

যদি আমরা জানি যে লেন এবং স্পেসের কোনও সীমাবদ্ধতা রয়েছে, তবে কেন আমরা প্রথমে স্থানটি প্রতিস্থাপন করতে পারি না? তারপরে আমরা জানি যে লেনকে বিভ্রান্ত করার কোনও জায়গা নেই।

len(replace(@string, ' ', '-')) - len(replace(replace(@string, ' ', '-'), ',', ''))

0
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'

0

ড্যারল লি আমার মনে হয় এর বেশ ভাল উত্তর আছে। প্রতিস্থাপন CHARINDEX()সঙ্গে PATINDEX(), এবং আপনি কিছু দুর্বল করতে পারি নাregex , খুব একটি স্ট্রিং বরাবর অনুসন্ধান করা হচ্ছে ...

পছন্দ করুন, বলুন আপনি এটি এর জন্য ব্যবহার করেন @pattern:

set @pattern='%[-.|!,'+char(9)+']%'

আপনি কেন এভাবে পাগল কিছু করতে চান?

বলুন আপনি সীমাবদ্ধ পাঠ্যের স্ট্রিংগুলি একটি মঞ্চের টেবিলে লোড করছেন, যেখানে ডেটা সম্বলিত ক্ষেত্রটি ভার্চার (8000) বা এনভারচার (সর্বোচ্চ) এর মতো কিছু ...

কখনও কখনও ETL (এক্সট্র্যাক্ট-ট্রান্সফর্ম-লোড) এর চেয়ে ডেটা সহ ELT (এক্সট্র্যাক্ট-লোড-ট্রান্সফর্ম) করা সহজ / দ্রুত হয় এবং এটি করার একটি উপায় হ'ল সীমিত রেকর্ডগুলি যেমন মঞ্চের টেবিলে থাকে তেমন লোড করা, বিশেষত যদি এসএসআইএস প্যাকেজের অংশ হিসাবে ব্যতিক্রমী রেকর্ডগুলি দেখার চেয়ে আপনি আরও সহজ উপায় দেখতে চাইতে পারেন ... তবে এটি ভিন্ন থ্রেডের জন্য পবিত্র যুদ্ধ।


0

নিম্নলিখিত একক অক্ষর এবং একাধিক অক্ষর অনুসন্ধান উভয়ের জন্য কৌশলটি করা উচিত:

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
          );

0

এই কোডটি ব্যবহার করুন, এটি নিখুঁতভাবে কাজ করছে। আমি একটি স্কয়ার ফাংশন তৈরি করেছি যা দুটি পরামিতি গ্রহণ করে, প্রথম পরম হ'ল দীর্ঘ স্ট্রিং যা আমরা এটি অনুসন্ধান করতে চাই এবং এটি স্ট্রিং দৈর্ঘ্য 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

0

আমি শেষ পর্যন্ত এই ফাংশনটি লিখি যা ইনপুটটিতে একটি চর উপসর্গ এবং প্রত্যয় যুক্ত করে সমস্ত সম্ভাব্য পরিস্থিতিগুলি আবরণ করা উচিত। এই চরটি অনুসন্ধান প্যারামিটারে বর্ণিত চরের যে কোনওটির থেকে আলাদা বলে মূল্যায়ন করা হয়, সুতরাং এটি ফলাফলকে প্রভাবিত করতে পারে না।

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 ,', ',')

0
Declare @MainStr nvarchar(200)
Declare @SubStr nvarchar(10)
Set @MainStr = 'nikhildfdfdfuzxsznikhilweszxnikhil'
Set @SubStr = 'nikhil'
Select (Len(@MainStr) - Len(REPLACE(@MainStr,@SubStr,'')))/Len(@SubStr)

0

এসকিউএল 2017 বা উচ্চতর ক্ষেত্রে আপনি এটি ব্যবহার করতে পারেন:

declare @hits int = 0
set @hits = (select value from STRING_SPLIT('F609,4DFA,8499',','));
select count(@hits)

0

এই টি-এসকিউএল কোডটি @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


0

এসকিউএল সার্ভারের জন্য 2017

declare @hits int = 0;
set @hits = (select count(*) from (select value from STRING_SPLIT('F609,4DFA,8499',',')) a);
select @hits;

-1

মানগুলি আনার জন্য আপনি নিম্নলিখিত সঞ্চিত পদ্ধতিটি ব্যবহার করতে পারেন।

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

এই সঞ্চিত পদ্ধতির 4 লাইন @c1তার প্রয়োজনীয় উত্তরটি সেট করে। কোডটি ব্যবহারের জন্য পূর্বের একটি বিদ্যমান টেবিলের প্রয়োজন বিবেচনা করে table1একটি হার্ড কোডিং ডিলিমিটার রয়েছে এবং এটি দুই মাস আগে থেকে স্বীকৃত উত্তরের মতো ইনলাইন ব্যবহার করা যাবে না, এই কোডটির বাকী কী ব্যবহার ?
নিক.এমসিডার্মাইড

-1

প্রতিস্থাপন / লেন পরীক্ষাটি সুন্দর, তবে সম্ভবত খুব অদক্ষ (বিশেষত স্মৃতির ক্ষেত্রে)। একটি লুপ সহ একটি সাধারণ ফাংশন কাজটি করবে।

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

প্রশংসনীয় আকারের যে কোনও টেবিল জুড়ে, একটি পদ্ধতিগত ফাংশন ব্যবহার করা অনেক বেশি অদক্ষ
নিক.এমসিডার্মাইড

ভাল যুক্তি. ব্যবহারের সংজ্ঞায়িত ফাংশনটির পরে কি বিল্ট লেন কলটি আরও দ্রুত হয়?
ডারেল লি

রেকর্ডের একটি বৃহত স্কেল, হ্যাঁ। যদিও আপনাকে নিশ্চিত হতে হবে আপনাকে বড় স্ট্রিং সহ একটি বড় রেকর্ডসেটে পরীক্ষা করতে হবে। এসকিউএল এ (যথা লুপগুলি) এড়াতে পারবেন তবে কখনও প্রক্রিয়াকরণের কোনও কিছুই লিখবেন না
নিক.এমসিডার্মিডেড

-3

সম্ভবত আপনার সেইভাবে ডেটা সংরক্ষণ করা উচিত নয়। কোনও ক্ষেত্রে কমা বিস্মৃত তালিকা সংরক্ষণ করা খারাপ অভ্যাস। অনুসন্ধানের জন্য এটি খুব অদক্ষ। এটি সম্পর্কিত টেবিল হওয়া উচিত।


এটা ভাবার জন্য +1। কেউ যখন কোনও ক্ষেত্রে কমা দ্বারা পৃথক করা ডেটা ব্যবহার করেন তখন আমি সাধারণত এটিই শুরু করি।
গুফা 20

6
এই প্রশ্নের উদ্দেশ্যটির অংশটি ছিল এর মতো বিদ্যমান ডেটা নেওয়া এবং এটি যথাযথভাবে পৃথক করা।
ওরিওন অ্যাড্রিয়ান

7
আমাদের মধ্যে কিছুকে লিগ্যাসি ডাটাবেস দেওয়া হয় যেখানে এটি করা হয়েছিল এবং আমরা এটি সম্পর্কে কিছুই করতে পারি না।
এডিডিয়োজার

@ মুলমথ, অবশ্যই এটি একটি উত্তর। আপনি সমস্যাটিকে লক্ষণ হিসাবে দেখান না। সমস্যাটি ডাটাবেস ডিজাইনের সাথে।
এইচএলজিএম

1
@HLGEM প্রশ্ন পারে একটি সমস্যা নির্দেশ, কিন্তু এটা আরও সাধারণ বোঝা যাবে। প্রশ্নটি খুব ভাল স্বাভাবিক ডাটাবেসগুলির জন্য সম্পূর্ণ বৈধ।
জিমি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.