Sql 如何使用定界符从文本字段中提取第n个值

Sql 如何使用定界符从文本字段中提取第n个值,sql,sql-server,Sql,Sql Server,在SQL表中,我有一个值为“黄|绿|蓝”的文本列和另一个值为数字的列。此数值定义要提取的文本列的哪一部分。文本列中的值用“|”分隔符分隔 例如: 如果数值为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 Kat

在SQL表中,我有一个值为“黄|绿|蓝”的文本列和另一个值为数字的列。此数值定义要提取的文本列的哪一部分。文本列中的值用“|”分隔符分隔

例如: 如果数值为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

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

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

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

同样,如果您使用SQL Server 2016+,您可以尝试使用REPLACE将文本数据转换为有效的JSON数组,将“Yellow | Green | Blue”转换为“[Yellow,Green,Blue]”,然后使用带有默认模式的OPENJSON以表的形式检索此JSON数组,表中有键列,值和类型键列包含指定数组中元素的索引

输入:

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

而不是想出一个解决这个问题的办法,例如使用字符串分割函数-你可以通过搜索sql server字符串分割来回答这类问题,如果您经常需要这样做,您最好将数据标准化,即不要在单个字段中放入多个值。或者在CTE中进行拆分您的服务器版本是什么?提供示例数据和所需结果。