SQL如何返回以逗号分隔的其他子字符串位置中的列值

SQL如何返回以逗号分隔的其他子字符串位置中的列值,sql,sql-server,indexing,substring,charindex,Sql,Sql Server,Indexing,Substring,Charindex,我的第一篇帖子!我希望你能帮助我:) 我在SQL 2017工作,我有这样一个表: +----+------------------+------------------+ |ID | Col1 | Col2| +-----+------------------+------------------+ | 110 | 450,2,50,110,600 | 3,45,30,901,1001 | | 250 | 2,250,300,1 | 1,33,540,900 | | 45 |

我的第一篇帖子!我希望你能帮助我:)

我在SQL 2017工作,我有这样一个表:

+----+------------------+------------------+
|ID | Col1 | Col2|
+-----+------------------+------------------+
| 110 | 450,2,50,110,600 | 3,45,30,901,1001 |
| 250 | 2,250,300,1      | 1,33,540,900     |
| 45  | 1,45,320         | 200,444,600      |
+-----+------------------+------------------+

逻辑是在Col1中找到ID位置,并基于该位置返回Col2中的子字符串

例如:

ID 110匹配Col1中的第四个位置,因此应该在Col2中返回901值。
ID 250匹配Col1中的第二个位置,因此应该在Col2中返回33个值。
ID 45匹配Col1中的第二个位置,因此应该在Col2中返回400值。

我做了不同的尝试,但没有成功,可能是我走错了方向

你能帮个忙吗

我想要的输出是Col2的特定值

谢谢

对于SQL Server 2016+(由于支持字符串分割,我不打算为早期版本做一个

DECLARE @BadDesign table (ID int, Col1 varchar(200), Col2 varchar(200));

INSERT @BadDesign VALUES
    (110,'450,2,50,110,600', '3,45,30,901,1001'),
    (250,'2,250,300,1', '1,33,540,900'),
    (45 ,'1,45,320', '200,444,600')    

SELECT
    * 
FROM
    @BadDesign B
    CROSS APPLY
    (SELECT 
       rn = ROW_NUMBER() OVER (ORDER BY (SELECT 1)), value 
     FROM  
        STRING_SPLIT(B.Col1, ',')
    ) b1
    CROSS APPLY
    (SELECT 
        rn = ROW_NUMBER() OVER (ORDER BY (SELECT 1)), value
     FROM
        STRING_SPLIT(B.Col2, ',')
     ) b2
WHERE
    B.ID = b1.value AND b1.rn = b2.rn
不保证字符串分割输出的行数一致性

编辑:还需要或更高版本(SQL Server 2016)

STRING_SPLIT函数仅在兼容级别下可用 130.如果您的数据库兼容性级别低于130,SQL Server将无法找到并执行STRING_SPLIT函数。您 可以使用以下命令更改数据库的兼容级别 命令:ALTER DatabaseName SET COMPABILITY_LEVEL=130


使用自定义字符串拆分函数(此答案使用Aaron Bertrand编写的函数),因此不限制在SQL2016上的使用+

CREATE FUNCTION dbo.SplitStringsOrdered (
      @List         NVARCHAR(2000)
    , @Delimiter    NVARCHAR(32)
)
RETURNS TABLE
AS
RETURN (
        SELECT
            rn  = ROW_NUMBER() OVER (ORDER BY Number)
            , Item
        FROM
            (
                SELECT
                    Number
                    , Item = LTRIM(RTRIM(SUBSTRING(
                                                    @List
                                                    , Number
                                                    , CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number
                                                )
                                        )
                                )
                FROM
                    (
                        SELECT  ROW_NUMBER() OVER (ORDER BY [object_id])
                        FROM
                            sys.all_objects
                    ) AS n(Number)
                WHERE
                    Number                                                  <= CONVERT(INT, LEN(@List))
                AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter))  = @Delimiter
            ) AS y
    );
GO

你能在问题中包括你希望最终输出是什么样子吗?不要像这样将CSV存储在SQL表中。即使你得到了答案,它也会很难使用/维护。SQL Server的版本是什么?我同意@TimBiegeleisen。这里唯一有意义的答案是修复你的数据模型。你所拥有的违反了1NF and很难使用。请记住,很多人不拥有db,他们不设计db,但仍必须在交给他们的特定条件下工作。因此,说这是糟糕的设计的评论是真实的,但在这里毫无帮助…嗨@gbn。非常感谢你的回答!我收到了无效的对象名称“STRING\u SPLIT”消息当我运行你的脚本时。我正在使用SQL 2017。根据文档检查数据库兼容性级别是的,这是允许的,早期版本我提供+1。我感谢+1@gbnHi@Cool\u Br33ze!感谢你的回答!它工作了!!你的脚本返回了我需要的:)+1。顶@迪尼斯丰塞卡我很乐意帮忙
DECLARE @BadDesign table (ID int, Col1 varchar(200), Col2 varchar(200));

INSERT @BadDesign VALUES
    (110,'450,2,50,110,600', '3,45,30,901,1001'),
    (250,'2,250,300,1', '1,33,540,900'),
    (45 ,'1,45,320', '200,444,600')    

SELECT
    B.*, Col1Value=b1.Item, Cal2Value = B2.Item
FROM
    @BadDesign B
    CROSS APPLY
    (SELECT 
       rn = ROW_NUMBER() OVER (ORDER BY (SELECT 1)), F.Item
     FROM  
        dbo.SplitStringsOrdered(B.Col1, ',') F
    ) b1
    CROSS APPLY
    (SELECT 
        rn = ROW_NUMBER() OVER (ORDER BY (SELECT 1)), F1.Item
     FROM
        dbo.SplitStringsOrdered(B.Col2, ',') F1
     ) b2
WHERE
    b1.rn = b2.rn