SQL Server создает строки из пользовательского текста с разделителями - PullRequest
0 голосов
/ 31 мая 2019

Я рассчитываю выбросы CO2 для маршрутов полетов.Маршрут полета может состоять из 1 прыжка, например, DXB / CDG или ABJ / ADD / BKK / KUL / ADD / ABJ, что составляет 5 прыжков.Моя задача состоит в том, чтобы мне нужно было разбить маршрутную информацию на индивидуальную информацию о рейсе, поскольку выбросы CO2 рассчитываются для каждого рейса:

Источник : ABJ/ADD/BKK/KUL/ADD/ABJ

и преобразовать его в:

enter image description here

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Я бы предложил такой подход:

DECLARE  @fligth VARCHAR(100)='ABJ/ADD/BKK/KUL/ADD/ABJ';

WITH Casted(flightXML) AS
    (SELECT CAST('<x>' + REPLACE(@fligth,'/','</x><x>') + '</x>' AS XML))
,Tally(Nmbr) AS 
    (SELECT TOP((SELECT flightXML.value('count(/x)','int') FROM Casted)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
SELECT flightXML.value('(/x[sql:column("Nmbr")]/text())[1]','varchar(10)') AS FromAirport
      ,flightXML.value('(/x[sql:column("Nmbr")+1]/text())[1]','varchar(10)') AS ToAirport
FROM Casted
CROSS JOIN Tally
WHERE flightXML.value('(/x[sql:column("Nmbr")+1]/text())[1]','varchar(10)') IS NOT NULL;

Идея:

Мы преобразуем строку с разделителями в XML, заменив разделители тегами.Итак, мы получаем

<x>ABJ</x>
<x>ADD</x>
<x>BKK</x>
<x>KUL</x>
<x>ADD</x>
<x>ABJ</x>

Теперь XQuery позволяет как получать значения по их позициям.Поэтому второй CTE создает подсчет на лету .Он вернет порядковые числа от n до n, где n - количество остановок в вашей строке.

В последнем запросе будет использоваться sql:column() для ввода числового числа в XQuery.Вы можете прочитать его как Найти <x> в позиции Nmbr и вернуть его содержимое.А теперь найдите <x> в позиции Nmbr+1.

1 голос
/ 01 июня 2019

Чтобы получить ожидаемые результаты, вы можете создать функцию, которая будет разбивать вашу строку на строки, используя предоставленные разделители.После этого вы можете выполнить дополнительную настройку или применить изменения к возвращенным данным на основе ваших требований.

Шаг 1: Создать функцию

CREATE  FUNCTION [dbo].[splitstring] ( @stringToSplit VARCHAR(MAX) ,@Delimiter VARCHAR(10))
RETURNS @returnList TABLE ([Word] [nvarchar] (500))
AS
BEGIN
    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT
    DECLARE @RN INT = 1

    WHILE CHARINDEX(@Delimiter, @stringToSplit) > 0
    BEGIN
        SELECT @pos  = CHARINDEX(@Delimiter, @stringToSplit)  
        SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

        INSERT INTO @returnList([Word],RN)
        SELECT @name,@RN

        SET @RN = @RN + 1

        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    END

    INSERT INTO @returnList([Word],RN)
    SELECT @stringToSplit,@RN

RETURN
END

Шаг 2: Получить необходимые данные с помощью этой функции

SELECT A.Word+'/'+B.Word FROM
(
    SELECT Word,RN 
    FROM [dbo].[splitstring]('ABJ/ADD/BKK/KUL/ADD/ABJ','/') 
) A
INNER JOIN 
(
    SELECT Word,RN 
    FROM [dbo].[splitstring]('ABJ/ADD/BKK/KUL/ADD/ABJ','/')
)B ON A.RN = B.RN-1

Вывод будет -

ABJ/ADD
ADD/BKK
BKK/KUL
KUL/ADD
ADD/ABJ
...