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

时间:2018-03-13 14:33:19

标签: 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 | 1,45,320 | 200,444,600 | +-----+------------------+------------------+

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

示例:

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

我做了不同的尝试但没有取得任何成功,可能我的方向错误。

你能帮忙吗?

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

谢谢!

2 个答案:

答案 0 :(得分:4)

对于SQL Server 2016+(由于STRING_SPLIT支持,我不会在之前做一个

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

不保证RING_NUMBER在STRING_SPLIT的输出上的一致性。

编辑:还需要database compatibility to be 130或更高版本(SQL Server 2016)

  

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

答案 1 :(得分:4)

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

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MjA5Mzg2MTcsIm5iZiI6MTUyMDkzODYxNywianRpIjoiZTZiNmViNTItMTI4NC00NzA5LWEwYTMtOTk5YTM4YmIyMTcwIiwiZXhwIjoxNTIwOTM5NTE3LCJpZGVudGl0eSI6eyJmaXJzdG5hbWUiOiJHZW9yZyIsImxhc3RuYW1lIjoiU2F0dGxlciIsImVtYWlsIjoiZ2VvcmdAc2F0dGxlci5pbyIsInV1aWQiOiI2ZTU1OGZjM2ExYjg0MTQ0YWQ1ODU1N2JlYWMxMjFkOCJ9LCJmcmVzaCI6dHJ1ZSwidHlwZSI6ImFjY2VzcyJ9.0EhkUXZpG4WTxhnDvQQp8i97GaNXoNyp24P7qLMRUPM", 
  "message": "successfully logged in - welcome", 
  "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MjA5Mzg2MTcsIm5iZiI6MTUyMDkzODYxNywianRpIjoiNzAxNTAxYWYtODJjMC00YmQ5LTg1YjAtZjQ0ZTNjNzgzYmY1IiwiZXhwIjoxNTIzNTMwNjE3LCJpZGVudGl0eSI6eyJmaXJzdG5hbWUiOiJHZW9yZyIsImxhc3RuYW1lIjoiU2F0dGxlciIsImVtYWlsIjoiZ2VvcmdAc2F0dGxlci5pbyIsInV1aWQiOiI2ZTU1OGZjM2ExYjg0MTQ0YWQ1ODU1N2JlYWMxMjFkOCJ9LCJ0eXBlIjoicmVmcmVzaCJ9.gRH3nJQEaBc2_0iZ9E9fhGg-9i-fil8c5SOvh8Tvsbg", 
  "request_id": "037dd993-1c19-4c68-8e5a-e060e11d3ce8", 
  "status": "OK"
}

修改@gbn在他/她的答案中创建的查询 - 这是允许的吗?

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