Как извлечь n-ое значение из текстового поля с разделителями - PullRequest
1 голос
/ 23 мая 2019

В таблице SQL у меня есть текстовый столбец со значением 'Yellow | Green | Blue' и другой столбец с числовым значением. Это числовое значение определяет, какая часть текстового столбца будет извлечена. Значения в текстовом столбце разделены знаком '|' Сепаратор.

Например: Если числовое значение равно 0, 1-я часть текстового поля должна быть извлечена: Желтый

Если числовое значение равно 1, следует извлечь 2-ю часть текстового поля: Зеленый

и т. Д.

Есть ли способ, как извлечь его динамически? Значение без использования оператора CASE, например:

case when u.UD_2 =0 then 'Yellow' when u.UD_2=1 then 'Green' when u.UD_2=3 then 'Blue' end Kategorie

ОБНОВЛЕНИЕ: мы используем SQL Server 2016

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Один из возможных подходов - разделить текстовые данные на подстроки и получить каждую позицию подстроки.

Начиная с SQL Server 2016, вы можете использовать STRING_SPLIT() для разделения строки, но в вашем случае это неопция, потому что эта функция возвращает таблицу со всеми подстроками, но они не упорядочены, и порядок подстрок не гарантируется.

Опять же, если вы используете SQL Server 2016+, вы можете попытаться преобразовать текстовые данные в действительный массив JSON, используя REPLACE() ('Yellow|Green|Blue' преобразуется в '["Yellow","Green","Blue"]') и после этого виспользуйте OPENJSON() со схемой по умолчанию для извлечения этого массива JSON в виде таблицы, в которой есть столбцы key, value и type (столбец key содержит индекс элемента в указанном массиве).

Ввод:

CREATE TABLE #Data (
   TextValue nvarchar(max),
   IndexValue int
)
INSERT INTO #Data
   (TextValue, IndexValue)
VALUES
   ('Yellow|Green|Blue', 0),
   ('Yellow|Green|Blue', 1)

T-SQL:

SELECT d.TextValue, d.IndexValue, j.[value] AS [Value]
FROM #Data d
CROSS APPLY OPENJSON(CONCAT(N'["', REPLACE(d.TextValue, N'|', N'","'), N'"]')) j
WHERE d.IndexValue = j.[key]

Выход:

---------------------------------------
TextValue           IndexValue  Value
---------------------------------------
Yellow|Green|Blue   0           Yellow
Yellow|Green|Blue   1           Green
1 голос
/ 23 мая 2019

Это должно работать для вас, в подзапросе извлекайте каждую категорию для разделения столбцов, а после нее используйте инструкцию case, чтобы выбрать нужную категорию.

select case sep when 0 then x.[0] when 1 then x.[1] when 2 then x.[2] end as Kategorie
from (
select *
    ,LEFT(val, CHARINDEX('|', val) - 1) AS '0'
    ,LEFT(STUFF(SUBSTRING(val, CHARINDEX('|', val), LEN(val)), 1, 1, ''), CHARINDEX('|', STUFF(SUBSTRING(val, CHARINDEX('|', val), LEN(val)), 1, 1, '')) - 1) AS '1'
    ,SUBSTRING(SUBSTRING(val, CHARINDEX('|', val), LEN(val)), CHARINDEX('|', val) + 1, LEN(val)) AS '2'
from #test
)x

Пример данных:

create table #test 
(
    val nvarchar(500),
    sep int
)
insert into #test values 
('Yellow|Green|Blue', 0),
('Yellow|Green|Blue', 1),
('Yellow|Green|Blue', 2)

Примечание: это работает, только если есть точные 3 значения, разделенные |

ОБНОВЛЕНИЕ

И это динамический способчтобы достичь этого, не имеет значения, сколько категорий будет разделено:

SELECT x.Kategorie 
FROM (
    SELECT DISTINCT node.s.value('.', 'NVARCHAR(500)') AS Kategorie
          ,ROW_NUMBER() OVER (PARTITION BY sep ORDER BY (SELECT NULL)) - 1 as rn 
    FROM (
        SELECT sep
            ,CAST('<M>' + REPLACE(val, '|', '</M><M>') + '</M>' AS XML) AS Kategorie
        FROM #test
        ) AS s
    CROSS APPLY Kategorie.nodes('/M') AS node(s)
)x
JOIN #test AS t ON t.sep = x.rn
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...