将字符串分成SQL Query部分

时间:2018-01-29 12:30:59

标签: sql sql-server

我尝试将此字符串剪切为3或4个部分,最多只能包含40个字符。如果第40个字符在一个单词之间我必须找到最后一个空格然后剪切并放入地址1,然后从我停止我必须再次重新计算到40个字符,如果第40个字符仍然在一个单词的中间我必须返回并找到最后一个空格,依此类推,直到整个字符串被分割。 这是我目前的代码,我的想法。希望你能帮帮我。

declare @test varchar(150)
set @test = 'GTB INDUSTRIAL NETWORK DAVAO I GTB INDUSTRIAL NETWORK DAVAO I DOOR 10 2F SJRDC BLDG PHASE 1 INSULAR SUBD LANANG'



Select REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40)))),len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
                CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40)))))  



Select Substring(@test,
Len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
len(Substring(@test,0,40)))
)),40),
len(Substring(@test,Len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
len(Substring(@test,0,40)))
)),40))             



Select SUBSTRING(@test,((len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
                CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40)))))+2) + 
                len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
                CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40))))) +4 )
                , 40), lEN(sUBSTRING(@test,((len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
                CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40)))))+2) + 
                len(REVERSE(SUBSTRING(REVERSE(Substring(@test,0,40)),
                CHARINDEX(' ',REVERSE(Substring(@test,0,40))),
                len(Substring(@test,0,40))))) +4 )
                , 40))

4 个答案:

答案 0 :(得分:0)

这是一个你可以使用的相当简单的算法(示意图,而不是实际运行的代码):

  1. 声明变量@_Chunk_Start INT = 1,@ _ Chunk_End INT = 40,@_Test_End VARCHAR(3),
  2. 创建一个循环,
  3. 检索三个为“SET @Test_End = SUBSTRING(@test,@ _ Chunk_Start + 38,3)
  4. 这将为你提供第39,40和41个字符;
  5. “在单词的中间”表示所有3个字符都是字母;
  6. 如果第40个字符为空白或第40个字符不是空白但是第41个字符,则从@_Chunk_Start切换到@_Chunk_Start + 39,
  7. 如果第40和第41个字符不是空白,请输入一个小循环,将@_Chunk_End的值减1,直到得到空白; chop,将@_Chunk_Start的新值设置为@_Chunk_End + 1并转到主循环的下一个循环。
  8. 希望这有帮助。

答案 1 :(得分:0)

一种相当务实但相当快速的方法,适用于字,省略任何高级复杂逻辑,是:

declare @test varchar(150)
set @test = 'GTB INDUSTRIAL NETWORK DAVAO I GTB INDUSTRIAL NETWORK DAVAO I DOOR 10 2F SJRDC BLDG PHASE 1 INSULAR SUBD LANANG';

WITH Splittable(Casted) AS 
(
    SELECT CAST('<x>' +  REPLACE((SELECT @test AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML) 
)
,Counted AS
(
    SELECT part.value('.','nvarchar(max)') AS Part
          ,LEN(part.value('.','nvarchar(max)'))+1 AS LengthWithBlank 
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNr
    FROM Splittable
    CROSS APPLY Casted.nodes('/x') AS B(part)
)
,Grouped AS
(
    SELECT *
          ,SUM(LEN(Part)) OVER(ORDER BY RowNr) /40 AS Grp
    FROM Counted
)
SELECT g1.Grp
      ,(SELECT g2.Part + ' '
        FROM Grouped AS g2
        WHERE g2.Grp=g1.Grp
        ORDER BY g2.RowNr
        FOR XML PATH(''),TYPE 
       ).value('.','nvarchar(max)')
FROM Grouped AS g1
GROUP BY g1.Grp;

这将首先将字符串拆分为其单词并将其返回并按每个部分的长度返回。

累积的SUM() OVER()整数除法 40,这会产生“群组”。最终的选择将返回每个组,结果如下:

Grp [splitted text]
0   GTB INDUSTRIAL NETWORK DAVAO I GTB INDUSTRIAL 
1   NETWORK DAVAO I DOOR 10 2F SJRDC BLDG PHASE 1 
2   INSULAR SUBD LANANG 

HINT

这种方法不准确!(有些结果大于40),但很多短文都很好。您可以将CTE“Grouped”的结果继续使用另一种方法。

答案 2 :(得分:0)

这是一种Recursive CTE方法。你的字符串不是那么长,所以你可以多次复制递归部分而不需要递归。

declare @test varchar(150)
set @test = 'GTB INDUSTRIAL NETWORK DAVAO I GTB INDUSTRIAL NETWORK DAVAO I DOOR 10 2F SJRDC BLDG PHASE 1 INSULAR SUBD LANANG'

;with cte as (
    select @test txt, cast('' as varchar(200)) res
    union all
    select
        cast(stuff(txt, 1, len(lres) + 1, '') as varchar(150)), cast(lres as varchar(200))c
    from
        cte
        cross apply (select reverse(substring(txt, 1, 40)) rev_txt) ca2
        cross apply (select reverse(right(rev_txt, len(rev_txt) - charindex(' ', rev_txt))) isspace) ca4
        cross apply (select case when substring(txt, 41, 1) = ' ' then substring(txt, 1, 40) else isspace end lres) ca5
    where
        len(txt) > 0
)

select res from cte
where len(res) > 0

答案 3 :(得分:0)

我把它作为一个新答案,因为这是一个完全不同的方法,然后是我的第一个答案。这是确切的,但不是那么快:

declare @test varchar(150)
set @test = 'GTB INDUSTRIAL NETWORK DAVAO I GTB INDUSTRIAL NETWORK DAVAO I DOOR 10 2F SJRDC BLDG PHASE 1 INSULAR SUBD LANANG';

WITH recCTE AS
(
    SELECT @test AS Original 
          ,1 AS StartPos
          ,SUBSTRING(@test,1,1) AS SingleChar
          ,1 AS RunningPos
    UNION ALL
    SELECT Original
          ,CASE WHEN SUBSTRING(@test,RunningPos +1,1)=' ' AND CHARINDEX(' ',Original,RunningPos+2)-StartPos >=40 THEN RunningPos+2 ELSE StartPos END 
          ,SUBSTRING(@test,RunningPos +1,1) AS SingleChar
          ,RunningPos +1
    FROM recCTE 
    WHERE RunningPos<LEN(Original)
)
,GroupedCharacterList AS
(
    SELECT *
    FROM recCTE
)
SELECT LTRIM(RTRIM((
        SELECT SingleChar AS [*]
        FROM GroupedCharacterList AS gl2
        WHERE gl2.StartPos=gl.StartPos
        ORDER BY gl2.RunningPos
        FOR XML PATH(''),TYPE
       ).value('.','nvarchar(max)')))
FROM GroupedCharacterList AS gl
GROUP BY StartPos
OPTION (MAXRECURSION 0);

递归CTE将逐个字符地读取。如果找到空白,它将查找字符串中的下一个空白并进行一些计算。如果下一个空白超过最大长度,则当前空白为新StartPos,然后流程继续。

这最终被分组并重新协调