如何使用分隔符从文本字段中提取第n个值

时间:2019-05-22 23:00:47

标签: sql sql-server

在SQL表中,我有一个值为'Yellow | Green | Blue'的文本列和另一个具有数值的列。此数值定义要提取的文本列的哪一部分。文本列中的值用'|'分隔分隔符。

例如: 如果数值为0,则应提取文本字段的第一部分:黄色

如果数值为1,则应提取文本字段的第二部分:绿色

以此类推。

有没有一种方法可以动态地提取它? 不使用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 个答案:

答案 0 :(得分:0)

这应该对您有用,在子查询中,将每个类别提取为单独的列,然后,使用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

答案 1 :(得分:0)

一种可能的方法是将文本数据拆分为子字符串并获取每个子字符串的位置。

从SQL Server 2016开始,您可以使用STRING_SPLIT()拆分字符串,但是在您的情况下,这不是一个选择,因为此函数返回包含所有子字符串的表,但它们的顺序和顺序不一不能保证子字符串。

同样,如果您使用SQL Server 2016+,则可以尝试使用JSON将文本数据转换为有效的REPLACE()数组('Yellow|Green|Blue'转换为'["Yellow","Green","Blue"]' ),然后在默认模式下使用OPENJSON()将此JSON数组作为表检索,该数组具有列keyvaluetype({{1 }}列包含指定数组中元素的索引。

输入:

key

T-SQL:

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

输出:

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]