2013-10-02 4 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», то есть: нет никакой запятой между парой.

Я не могу изменить исходные данные, поскольку он используется программой поставщика. Мне нужно манипулировать строкой, чтобы удалить каждую 1 из 2 запятых или, если это не удается, получить регулярное выражение в 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', то есть. space плюс группа захвата 1

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. commasCTE вычисляет позиции всех запятых в строке @coords, возвращая результаты в виде набора строк. Основной SELECT используется оператор присваивания. Требуется каждый number в наборе commas и удаляет символ в соответствующей позиции в @coords, заменяя его пробельным символом (все с помощью функции STUFF).

Вы можете использовать этот SQL Fiddle demo, чтобы играть в запрос.

0

Спасибо за код :-)

У меня был немного другой сценарий, однако создал функцию с помощью «Chue х» код для добавления символа «#» на каждый третий «;»

/*** 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 
Смежные вопросы