6

文字列 (特定の列から) を単語を分割せずに n 桁の文字に分割し、それぞれの結果を独自の行にする方法はありますか?

例:

2012-04-24 Change request #3 for the contract per terms and conditions and per John Smith in the PSO department  Customer states terms should be Net 60 not Net 30.  Please review signed contract for this information.

結果:

2012-04-24 Change request #3 for the contract per terms and conditions and per John Smith in the
PSO department  Customer states terms should be Net 60 not Net 30.
Please review signed contract for this information.

最後のスペースを見つけるために使用できることはわかっていcharindexますが、残りのスペースを取得して行として返す方法がわかりません。

4

4 に答える 4

4

このようなことを試してください。以下の実装のSQL関数を作成できるかもしれません。

DECLARE @Str VARCHAR(1000)
SET @Str = '2012-04-24 Change request #3 for the contract per terms and conditions and per John Smith in the PSO department  Customer states terms should be Net 60 not Net 30.  Please review signed contract for this information.'

DECLARE @End INT
DECLARE @Split INT

SET @Split = 100

declare @SomeTable table
(
  Content varchar(3000)
)


WHILE (LEN(@Str) > 0)
BEGIN
    IF (LEN(@Str) > @Split)
    BEGIN
        SET @End = LEN(LEFT(@Str, @Split)) - CHARINDEX(' ', REVERSE(LEFT(@Str, @Split)))
        INSERT INTO @SomeTable VALUES (RTRIM(LTRIM(LEFT(LEFT(@Str, @Split), @End))))
        SET @Str = SUBSTRING(@Str, @End + 1, LEN(@Str))
    END
    ELSE
    BEGIN
        INSERT INTO @SomeTable VALUES (RTRIM(LTRIM(@Str)))
        SET @Str = ''
    END
END

SELECT *
FROM @SomeTable

出力は次のようになります。

2012-04-24 Change request #3 for the contract per terms and conditions and per John Smith in the
PSO department  Customer states terms should be Net 60 not Net 30.  Please review signed contract
for this information.
于 2012-06-01T15:20:54.180 に答える
2

それができるかどうかを確認するために、ループしないソリューションを思いつきました。区切り文字に基づいて文字列を分割するのは、他の誰かの機能に基づいています。

注: これには、トークンの最大長を事前に知っておく必要があります。この関数は、指定された行の長さよりも長いトークンに遭遇すると、行を返すのを停止します。おそらく他にもバグが潜んでいるので、このコードは慎重に使用してください。

CREATE FUNCTION SplitLines
(
    @pString    VARCHAR(7999),
    @pLineLen   INT,
    @pDelim     CHAR(1)
)
RETURNS TABLE
   WITH SCHEMABINDING
AS  
RETURN
WITH
      E1(N) AS ( --=== Create Ten 1's
                 SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 --10
               ),
      E2(N) AS (SELECT 1 FROM E1 a, E1 b),   --100
      E4(N) AS (SELECT 1 FROM E2 a, E2 b),   --10,000
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT N)) FROM E4),
lines AS (
  SELECT TOP 1
         1 as LineNumber,
         ltrim(rtrim(SUBSTRING(@pString, 1, N))) as Line,
         N + 1 as start
  FROM cteTally
  WHERE N <= DATALENGTH(@pString) + 1
    AND N <= @pLineLen + 1
    AND SUBSTRING(@pString + @pDelim, N, 1) = @pDelim
  ORDER BY N DESC
UNION ALL
  SELECT LineNumber, Line, start
  FROM (
    SELECT LineNumber + 1 as LineNumber,
           ltrim(rtrim(SUBSTRING(@pString, start, N))) as Line,
           start + N + 1 as start,
           ROW_NUMBER() OVER (ORDER BY N DESC) as r
    FROM cteTally, lines
    WHERE N <= DATALENGTH(@pString) + 1 - start
      AND N <= @pLineLen
      AND SUBSTRING(@pString + @pDelim, start + N, 1) = @pDelim
  ) A
  WHERE r = 1
)
SELECT LineNumber, Line
FROM lines

それは実際には非常に高速で、それに参加するなどのクールなことを行うことができます。テーブルのすべての行から最初の「行」を取得する簡単な例を次に示します。

declare @table table (
  id int,
  paragraph varchar(7999)
)
insert into @table values (1, '2012-04-24 Change request #3 for the contract per terms and conditions and per John Smith in the PSO department  Customer states terms should be Net 60 not Net 30.  Please review signed contract for this information.')
insert into @table values (2, 'Is there a way to split a string (from a specific column) to n-number chars without breaking words, with each result in its own row?')

select t.id, l.LineNumber, l.Line, len(Line)
from @table t
cross apply SplitLines(t.paragraph, 42, ' ') l
where l.LineNumber = 1
于 2012-06-01T20:27:04.323 に答える
2

いくつかの記事を読みましたが、それぞれにエラーが発生したり、パフォーマンスが低下したり、必要な長さのチャンクで機能したりしませんでした。以下のこの記事でも、私のコメントを読むことができます。最後に、良い答えを見つけて、この質問で共有することにしました。さまざまなシナリオでパフォーマンスを確認しませんでしたが、チャンクの長さが小さくても大きくても問題なく動作すると思います。これはコードです:

CREATE function SplitString
(   
    @str varchar(max),
    @length int
)
RETURNS @Results TABLE( Result varchar(50),Sequence INT ) 
AS
BEGIN

DECLARE @Sequence INT 
SET @Sequence = 1

    DECLARE @s varchar(50)
    WHILE len(@str) > 0
    BEGIN
        SET @s = left(@str, @length)
        INSERT @Results VALUES (@s,@Sequence)

        IF(len(@str)<@length)
        BREAK

        SET @str = right(@str, len(@str) - @length)
        SET @Sequence = @Sequence + 1
    END
    RETURN 
END

およびソースは、この質問に対する@Rhynoの回答です: TSQL UDF To Split String Every 8 Characters

この助けを願っています。

于 2014-10-20T09:08:08.610 に答える
0

これは少し遅いことは知っていますが、再帰cteを使用するとこれを実現できます。

また、開始インデックスの乗数としてサブストリングにフィードする一連の数値を含むシードテーブルを利用することもできます。

于 2012-06-01T18:51:20.947 に答える