2017-01-03 5 views
2

で単語の複数の発生を置き換える私はこのような値を含む列EventとSQL Serverのテーブルを持っている:SQL Serverの:1

[Event] 
---------------------------------------- 
Payment stopped, Claim, Claim, Claim 
Claim 
Claim, Claim, Claim 
Claim, Claim, Payment stopped, Case Closed 

今、ユーザーには、サマリー・カウントがこのコラムを見たいです単語「請求」が、下の列は単語の主張は「400回まで提示でき

[Event] 
------------------------------------- 
Payment stopped, 3 Claims 
Claim 
3 Claims 
2 Claims, Payment stopped, Case Closed 

のように、彼らは(3値の開始に数を維持する気にしないになりますようにクレーム、支払い停止)、または値の終了(支払い停止、3クレーム)。私はこの言葉のカウントを得ることができるudfを持っていますが、カンマを削除すると、スペースは本当に難しいようです。

これを行う方法はありますか(udfの有無にかかわらず)?私はSQL Server 2008を使用しています。

+1

ですフロントエンドのための仕事ではなく、私にはdb。csvを分割して、それを再フォーマットし、そしてsそれを一緒につなぎ合わせることは、SQLを使ったPITAになるでしょう。 – Jamiec

+0

これはSSRSレポートです。あなたは、レポートデザイナーで利用可能なオプションで可能であると思いますか? – Saranya

+1

可能かもしれませんが、可能なことはテーブルを適切に設計することです。問題はありません。コンマ区切りの値を含む列は、操作する必要がありますが、レポートを戻す方法ではありません。イベント・テーブルとジャンクション・テーブルをレコードに戻す必要があります。 – Jamiec

答えて

1

まず、split関数を使用してアイテムをIDで分割し、各アイテムの数を取得する必要があります。その後、結果を結びつける必要があります。以下は、サンプルデータによるクエリです。以下は

declare @myevent table(id int identity,name varchar(max)); 

insert into @myevent select 'Payment stopped, Claim, Claim, Claim'; 
insert into @myevent select 'Claim'; 
insert into @myevent select 'Claim, Claim, Claim'; 
insert into @myevent select 'Claim, Claim, Payment stopped, Case Closed'; 

with cte as(
    select id,cast(count(item) over(partition by id,ltrim(rtrim(item))) as varchar(5)) + ' ' + ltrim(rtrim(item)) Item 
    from @myevent 
     cross apply dbo.Split(name,',') 
) 
,cte1 as(
    select distinct id,item 
    from cte 
) 
select distinct id 
     ,substring((select ','+item 
        from cte1 c1 
        where c1.id = c2.id 
        order by id 
        for xml path('') 
        ) 
        , 2, 1000 
       ) [result] 
from cte1 c2 

は、Split関数

CREATE FUNCTION [dbo].[Split] (
     @InputString VARCHAR(8000), 
     @Delimiter VARCHAR(50) 
) 

RETURNS @Items TABLE (
     Item VARCHAR(8000) 
) 

AS 
BEGIN 
     IF @Delimiter = ' ' 
     BEGIN 
      SET @Delimiter = ',' 
      SET @InputString = REPLACE(@InputString, ' ', @Delimiter) 
     END 

     IF (@Delimiter IS NULL OR @Delimiter = '') 
      SET @Delimiter = ',' 

     DECLARE @Item VARCHAR(8000) 
     DECLARE @ItemList VARCHAR(8000) 
     DECLARE @DelimIndex INT 

     SET @ItemList = @InputString 
     SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     WHILE (@DelimIndex != 0) 
     BEGIN 
      SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex) 
      INSERT INTO @Items VALUES (@Item) 

      -- Set @ItemList = @ItemList minus one less item 
      SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)[email protected]) 
      SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     END -- End WHILE 

     IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString 
     BEGIN 
      SET @Item = @ItemList 
      INSERT INTO @Items VALUES (@Item) 
     END 

     -- No delimiters were encountered in @InputString, so just return @InputString 
     ELSE INSERT INTO @Items VALUES (@InputString) 

     RETURN 

END -- End Function 

出力

id result 
1 1 Payment stopped,3 Claim 
2 1 Claim 
3 3 Claim 
4 1 Case Closed,1 Payment stopped,2 Claim,2 Claim 
+0

少なくともスプリット機能に関する詳細情報を提供する必要があります。 – TJB

+0

回答を更新してください。 – User

+0

ありがとうございますが、私は「クレーム」の単語数が必要です。 – Saranya

1

ある以下のスクリプトを試してみてください

DECLARE @V_WORD NVARCHAR(10) = 'Claim' 

DECLARE @TABLE TABLE 
( [Event] NVARCHAR(MAX)) 

INSERT INTO @TABLE 
VALUES('Payment stopped, Claim, Claim, Claim'),('Claim'),('Claim, Claim, Claim'),('Claim, Claim, Payment stopped, Case Closed') 

;WITH CTE 
AS (
     SELECT [Event] 
       ,CHARINDEX(@V_WORD,[Event],0) [stpos] 
       ,(LEN([Event]) - LEN(REPLACE([Event],@V_WORD,'')))/LEN(@V_WORD) AS [ECount] 
     FROM @TABLE 
) 

SELECT REPLACE([Event] 
       ,SUBSTRING([Event],[stpos],([ECount] * LEN(@V_WORD)) + (([ECount]-1) * 2)) 
       ,CAST([ECount] AS NVARCHAR) +' Claim' + 
        (CASE WHEN [ECount] > 1 THEN 's' ELSE '' END) 
       ) [Result] 
FROM CTE 

結果:

Payment stopped, 3 Claims 
1 Claim 
3 Claims 
2 Claims, Payment stopped, Case Closed 
+1

ありがとう、これは私が持っているテストデータで動作します。数時間後にライブデータでテストします。私のデータでは、利用可能な複数の請求がある場合、注文は変更されません。 – Saranya

0

私は、インポートプロセスとデータスキーマを見て、すべての異なるイベントを個々のテーブル行として保持する必要があるという意見に同意します。

ただし、これが不可能な場合は、cteやその他の機能を使用せずに、比較的簡単に必要な操作を行うことができます。それは、あなたの質問にを求めてきたものすべてであるとして、これは、言葉Claim以外では動作しないことに注意して:

declare @Event table(Event nvarchar(500)); 
insert into @Event values 
('Payment stopped, Claim, Claim, Claim') 
,('Claim') 
,('Claim, Claim, Claim') 
,('Claim, Claim, Payment stopped, Case Closed') 
,('Payment stopped, Case Closed'); 

select Event 
     ,case (len(Event) - len(replace(Event,'Claim','')))/5 
        when 0 then '' 
        when 1 then '1 Claim' + case when len(replace(Event,'Claim','')) > 0 then ', ' else '' end 
        else cast((len(Event) - len(replace(Event,'Claim','')))/5 as nvarchar(5)) + ' Claims' + case when len(replace(Event,'Claim','')) > 0 then ', ' else '' end 
       end 
      + case when len(replace(Event,'Claim','')) > 0 
        then replace(replace(replace(Event,', Claim',''),'Claim, ',''),'Claim','') 
        else '' 
        end as Result 
from @Event; 

出力:

Event          | Result 
````````````````````````````````````````````|```````````````````````````````````````` 
Payment stopped, Claim, Claim, Claim  | 3 Claims, Payment stopped 
Claim          | 1 Claim 
Claim, Claim, Claim       | 3 Claims, 
Claim, Claim, Payment stopped, Case Closed | 2 Claims, Payment stopped, Case Closed 
Payment stopped, Case Closed    | Payment stopped, Case Closed 
+0

アイテムの順序が変更された場合、クエリは失敗します。例: '請求、支払い停止、クレーム、請求'。私は3つのクレームの結果を得ています。、支払停止 – User

+0

@Srinath私は同じエラーを取得していません...あなたの例では、クレーム、支払いが停止、クレーム、クレーム '私は3のクレーム、停止した – iamdave

+0

私はあなたのクエリを実行した、私は3クレームを取得している、支払いが停止しました。余分なコンマを取得する – User

0

もう一つの方法は、スカラー関数でありますこれを行うために。

あなたの質問のスキーマ。

CREATE TABLE #Event (EVENT_LIST VARCHAR(MAX)) 

INSERT INTO #Event 
SELECT 'Payment stopped, Claim, Claim, Claim' 
UNION ALL 
SELECT 'Claim' 
UNION ALL 
SELECT 'Claim, Claim, Claim' 
UNION ALL 
SELECT 'Claim, Claim, Payment stopped, Case Closed' 

各レコードの各単語の数をカウントする必要があります。したがって、一度に行ごとに実行して結果を返す関数を作成する必要があります。ロジックと

機能:

CREATE FUNCTION [dbo].FN_REPEAT_COUNT(@VAR VARCHAR(MAX)) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 

SET @[email protected]+',' 
;WITH CTE AS --Recursive CTE for calculating ',' indexes 
(
    SELECT 1 INDX_FRM 
    , LEN(@VAR) LEN_VAR 
    , CHARINDEX(',',@VAR)+1 AS INDX_TO 

    UNION ALL 

    SELECT CAST(INDX_TO+1 AS INT) 
    , LEN_VAR 
    , CHARINDEX(',',SUBSTRING(@VAR,INDX_TO+1,LEN_VAR))+INDX_TO+1 

    FROM CTE WHERE INDX_TO<LEN_VAR 
) 
,CTE2 AS( --cte to generate records based on ',' index 
SELECT SUBSTRING(@VAR,INDX_FRM,INDX_TO-INDX_FRM-1) AS LIST FROM CTE 
) 
,CTE3 AS ( --cte for count of word Claim and making them back to column 
SELECT (
     SELECT CAST(COUNT(CASE 
         WHEN LIST = 'Claim' 
          THEN 1 
         ELSE NULL 
         END) AS VARCHAR(2)) + ' ' + LIST + ',' 
     FROM CTE2 
     GROUP BY LIST 
     FOR XML PATH('') 
     ) COUNTED 

) 
--Removing 0 and replacing ',' with Empty String 
SELECT @VAR = REPLACE(SUBSTRING(COUNTED,1,LEN(COUNTED)-1),'0','') FROM CTE3 
RETURN @VAR 
END 

そして今はちょうど下の

SELECT *, dbo.FN_REPEAT_COUNT(EVENT_LIST) AS FN_RES FROM #Event 

のようなあなたの列にスカラー関数を呼び出し、出力はこれはのように思える

╔════════════════════════════════════════════╦═══════════════════════════════════════╗ 
║     EVENT_LIST     ║    FN_RES     ║ 
╠════════════════════════════════════════════╬═══════════════════════════════════════╣ 
║ Payment stopped, Claim, Claim, Claim  ║ 3 Claim, Payment stopped    ║ 
║ Claim          ║ 1 Claim        ║ 
║ Claim, Claim, Claim      ║ 3 Claim        ║ 
║ Claim, Claim, Payment stopped, Case Closed ║ Case Closed,2 Claim, Payment stopped ║ 
╚════════════════════════════════════════════╩═══════════════════════════════════════╝