2013-10-02 245 views
3

我有一個字段,其中包含定義地理圍欄(多邊形)的緯度/長度座標的字符串。每個都用逗號分隔。用TSQL替換字符串中每個第二個字符的實例

如: '緯度,經度,緯度,經度,緯度,經度'
如: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中工作

回答

0

您可以像下面這樣推出自己的解析器。它使用字符串中的逗號來查找所有的經度/緯度值。它加到一起使用模式的所有值:緯度長,緯度長,...

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

0

我不知道你的正則表達式如何工作,但如果你用正則表達式預處理字符串,它可能會工作全球搜索和替換如下:

找到:,([^,]*(?:,|$))
替換:'$1'ie。空間加捕獲組1

1

你可以使用一個numbers tablea 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一個子集「中扮演」。 commasCTE計算@coords字符串中所有逗號的位置,並將結果作爲行集返回。主要的SELECT用於一個賦值語句。它需要設置commas集合中的每個number,並刪除@coords中相應位置的字符,並用空格字符替換它(全部藉助STUFF函數)。

您可以使用此SQL Fiddle demo玩查詢。

0

感謝您的代碼:-)

我不得不使用但「柱先生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 
0

就這樣結束了我的解決方案:

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 
相關問題