【问题标题】:Replace every 2nd instance of character in string with TSQL用 TSQL 替换字符串中每个第二个字符实例
【发布时间】:2013-10-02 22:57:51
【问题描述】:

我有一个字段,其中包含一串定义地理围栏(多边形)的纬度/经度坐标。每个都用逗号分隔。

例如:'lat,long,lat,long,lat,long'
例如:148.341158,-21.500773,148.341406,-21.504989,148.375136,-21.513174,148.401674,-21.535247,148.418044,-21.532767,148.408867,-21.511685,148.414075,-21.508461,148.36968,-21.432567,148.349094,-21.438768,148.346862, - 21.480187,148.341158,-21.500773,

我想将此与 MSSQL 中的地理类型一起使用 (http://msdn.microsoft.com/en-us/library/bb933971.aspx)

DECLARE @g geography;
SET @g = geography::STPolyFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326);
SELECT @g.ToString();

这似乎需要:'lat long, lat long, lat long' 即:这对之间没有逗号。

我无法更改源数据,因为它由供应商程序使用。我需要操纵字符串以删除 2 个逗号中的每 1 个,否则,让正则表达式在 TSQL 中工作

【问题讨论】:

    标签: sql-server regex tsql replace


    【解决方案1】:

    您可以使用numbers table(顺便说一句,a very handy tool for many purposes)来查找所有逗号的位置,然后仅使用奇数位置编号,在单个 SELECT 语句中将相应的逗号替换为空格。这就是我要说的:

    WITH commas AS (
      SELECT number, rn = ROW_NUMBER() OVER (ORDER BY number)
      FROM master.dbo.spt_values
      WHERE type = 'P'
        AND number BETWEEN 1 AND LEN(@coords)
        AND SUBSTRING(@coords, number, 1) = ','
    )
    SELECT
      @coords = STUFF(@coords, number, 1, ' ')
    FROM cte
    WHERE rn % 2 = 1
    ;
    

    在上述查询中,数字表的“部分”由system table master.dbo.spt_values 的子集“播放”。 commas CTE 计算@coords 字符串中所有逗号的位置,并将结果作为行集返回。主 SELECT 用于赋值语句。它获取commas 集合中的每个number 并删除@coords 中相应位置的字符,将其替换为空格字符(所有这些都在STUFF 函数的帮助下)。

    您可以使用此SQL Fiddle demo 来处理查询。

    【讨论】:

      【解决方案2】:

      这结束了我的解决方案:

      DECLARE @WorkingCoordList VARCHAR(max) = 'some lat,long,lat,long string'
      DECLARE @Processed INT = 0
      DECLARE @CommaLoc INT
      DECLARE @Count INT = 0
      
      WHILE @Processed = 0        
          BEGIN       
              SET @CommaLoc = PATINDEX('%,%', @WorkingCoordList)  
      
              IF @Count % 2 = 0   
              BEGIN   
                  SET @WorkingCoordList = STUFF(@WorkingCoordList, @CommaLoc, 1, ' ') --Convert comma to space
              END 
              ELSE    
              BEGIN   
                  SET @WorkingCoordList = STUFF(@WorkingCoordList, @CommaLoc, 1, '#') -- Convert comma to hash
              END 
      
              IF @CommaLoc = LEN(@WorkingCoordList)   
              BEGIN   
                  SET @WorkingCoordList = LEFT(@WorkingCoordList, LEN(@WorkingCoordList) - 1)  -- trim trailing ,
                  SET @WorkingCoordList = RTRIM(LTRIM(REPLACE(@WorkingCoordList, '#', ', '))) -- Convert all the hashes to commas
                  SET @Processed = 1
              END 
      
              SET @Count = @Count + 1 
          END 
      END
      

      【讨论】:

        【解决方案3】:

        您可以像下面这样滚动自己的解析器。它使用字符串中的逗号来查找所有纬度/经度值。它使用以下模式将所有值连接在一起:lat long, lat long, ...

        declare @list varchar(max) 
        declare @result varchar(max)
        declare @word varchar(max)
        declare @splitOn varchar(1)
        declare @wpos int
        declare @cpos int
        declare @wordCount int
        
        select @list = '148.341158,-21.500773,148.341406,-21.504989,148.375136,-21.513174,148.401674,-21.535247,148.418044,-21.532767,148.408867,-21.511685,148.414075,-21.508461,148.36968,-21.432567,148.349094,-21.438768,148.346862,-21.480187,148.341158,-21.500773,'
        select @splitOn = ','
        select @result = ''
        
        select @cpos = 0
        select @wpos = 1
        select @wordCount = 1
        
        while (@cpos <= len(@list))
        begin
            select @cpos = charindex(@splitOn, @List, @cpos)
            if (@cpos < 1) select @cpos = len(@list) + 1
        
            select @word = substring(@list, @wpos, @cpos - @wpos)
            select @result = @result + ' ' + @word
        
            if ((@wordCount % 2) = 0 and (@cpos < len(@list))) select @result = @result + ','
        
            select @cpos = @cpos + 1
            select @wpos = @cpos
            select @wordCount = @wordCount + 1
        end
        select @result as result
        

        这会产生以下字符串:

        148.341158 -21.500773,148.341406 -21.504989,148.375136 -21.513174,148.401674 -21.535247,148.418044 -21.532767,148.408867 -21.511685,148.414075 -21.508461,148.36968 -21.432567,148.349094 -21.438768,148.346862 -21.480187,148.341158 -21.500773 P>

        【讨论】:

          【解决方案4】:

          我不知道您的正则表达式是如何工作的,但如果您使用正则表达式预处理字符串,它可能会与全局搜索和替换一起使用,如下所示:

          查找:,([^,]*(?:,|$))
          替换:'$1' 即。空间加捕获组 1

          【讨论】:

            【解决方案5】:

            感谢代码:-)

            我有一个稍微不同的场景,但是使用“chue x”代码创建了一个函数,在每 3 个 ';' 处添加一个字符 '#'

            /*** My select query ***/
            SELECT        dbo.fn_AddEveryNthItem(a.MyString, ';','#', 3) AS Expr1
            FROM            dbo.MyTable as a
            

            函数如下

            /*** Function to add character for every nth item ***/
            Create function dbo.fn_AddEveryNthItem(@list varchar(1000), @splitOn varchar(1), @addChar varchar(1), @EveryNthItem int) 
            RETURNS VARCHAR(1000)
            AS
            BEGIN
            declare @word varchar(max)
            declare @result varchar(max) = ''
            declare @wpos int = 1
            declare @cpos int = 0
            declare @wordCount int =1
            
            while (@cpos <= len(@list))
            begin
                select @cpos = charindex(@splitOn, @List, @cpos)
                if (@cpos < 1) select @cpos = len(@list) + 1
            
                select @word = substring(@list, @wpos, @cpos - @wpos)
                select @result = @result + @splitOn + @word
            
                if ((@wordCount % @EveryNthItem) = 0 and (@cpos < len(@list))) select @result = @result + @addChar
            
                select @cpos = @cpos + 1
                select @wpos = @cpos
                select @wordCount = @wordCount + 1
            end
            Return @result
            end
            

            【讨论】:

              猜你喜欢
              • 2017-12-01
              • 2017-11-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-23
              • 2021-04-09
              • 2020-08-05
              • 2013-12-17
              相关资源
              最近更新 更多