Разбить строку на массив с помощью разделителя, получая элемент от второго до последнего в инструкции SELECT - PullRequest
1 голос
/ 23 октября 2019

Головы!

В моей базе данных есть столбец, который содержит следующие данные (примеры):

H-01-01-02-01

BLE-01-03-01

H-02-05-1.1-03

Задача состоит в том, чтобы получить второй или последний элемент массиваесли вы разделите это, используя символ "-". Строки имеют разную длину.

Таким образом, это будет результат с использованием вышеупомянутых данных:

02

03

1.1

В основном я ищу эквивалент следующей инструкции ruby ​​для использованияв операторе выбора в SQL-сервере:

"BLE-01-03-01".split("-")[-2]

Возможно ли это каким-либо образом в SQL Server? Потратив некоторое время на поиск решения, я нашел только те, которые работают для последнего или первого элемента.

Большое спасибо за любые подсказки или решения!

PS: версия SQL ServerMicrosoft SQL Server 2012

Ответы [ 4 ]

1 голос
/ 23 октября 2019

В качестве альтернативы вы можете попробовать это:.

- таблица макетов с некоторыми тестовыми данными для имитации вашей проблемы

DECLARE @mockupTable TABLE (ID INT IDENTITY, YourColumn VARCHAR(50));
INSERT INTO @mockupTable VALUES 
 ('H-01-01-02-01') 
,('BLE-01-03-01')
,('H-02-05-1.1-03');

- запрос

SELECT CastedToXml.value('/x[sql:column("CountOfFragments")-1][1]','nvarchar(10)') AS TheWantedFragment
FROM @mockupTable t
CROSS APPLY(SELECT CAST('<x>' + REPLACE(t.YourColumn,'-','</x><x>') + '</x>' AS XML))A(CastedToXml)
CROSS APPLY(SELECT CastedToXml.value('count(/x)','int')) B(CountOfFragments);

Идея вкратце:

Первый APPLY преобразует строку в XML, подобный этому

<x>H</x>
<x>01</x>
<x>01</x>
<x>02</x>
<x>01</x>

Второй APPLY сделает запрос в этот XML, чтобы получитьколичество фрагментовПоскольку APPLY добавит это как столбец к результирующему набору, мы можем использовать значение, используя sql:column(), чтобы получить искомый фрагмент по его позиции.

0 голосов
/ 23 октября 2019

Как я написал в своем комментарии - используя charindex с reverse.

Сначала создайте и заполните таблицу образцов ( Пожалуйста, сохраните нам этот шаг в ваших будущих вопросах):

DECLARE @T AS TABLE
(
    Col Varchar(100)
);

INSERT INTO @T (Col) VALUES
('H-01-01-02-01'),
('BLE-01-03-01'),
('H-02-05-1.1-03');

Запрос:

SELECT  Col, 
        LEFT(RIGHT(Col, AlmostLastDelimiter-1), AlmostLastDelimiter - LastDelimiter - 1) As SecondToLast
FROM @T 
CROSS APPLY (SELECT CharIndex('-', Reverse(Col)) As LastDelimiter) As A
CROSS APPLY (SELECT CharIndex('-', Reverse(Col), LastDelimiter+1) As AlmostLastDelimiter) As B

Результаты:

Col             SecondToLast
H-01-01-02-01   02
BLE-01-03-01    03
H-02-05-1.1-03  1.1
0 голосов
/ 23 октября 2019

Аналогично решению Zohar, но с использованием CTE вместо CROSS APPLY для предотвращения избыточности. Лично мне легче следовать этому, поскольку вы можете видеть, что происходит на каждом этапе. Хотя это не делает его лучшим решением;)

DECLARE @strings TABLE (data VARCHAR(50));
INSERT INTO @strings VALUES ('H-01-01-02-01') , ('BLE-01-03-01'), ('H-02-05-1.1-03');
WITH rev AS (
    SELECT
        data,
        REVERSE(data) AS reversed
    FROM
        @strings),
first_hyphen AS (
    SELECT
        data,
        reversed,
        CHARINDEX('-', reversed) + 1 AS first_pos
    FROM
        rev),
second_hyphen AS (
    SELECT
        data,
        reversed,
        first_pos,
        CHARINDEX('-', reversed, first_pos) AS second_pos
    FROM
        first_hyphen)
SELECT
    data,
    REVERSE(SUBSTRING(reversed, first_pos, second_pos - first_pos)) AS result
FROM
    second_hyphen;

Результаты:

data            result
H-01-01-02-01   02
BLE-01-03-01    03
H-02-05-1.1-03  1.1
0 голосов
/ 23 октября 2019

Попробуйте это

declare @input NVARCHAR(100)
declare @dlmt NVARCHAR(3);
declare @pos INT = 2
SET @input=REVERSE(N'H-02-05-1.1-03');
SET @dlmt=N'-';
SELECT 
    CAST(N'<x>' 
    + REPLACE(
                (SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH(''))
                    ,N'#DLMT#',N'</x><x>'
              ) + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...