SQL - STRING_SPLIT 字符串位置

标签 sql sql-server

我有一个包含两列逗号分隔字符串的表格。数据格式化的方式,两列中逗号分隔的项目数相等,colA 中的第一个值与 colB 中的第一个值相关,等等。 (这显然不是一种很好的数据格式,但这是我正在使用的格式。)

如果我有以下行(PrimaryKeyID | column1 | column2):

1 | a,b,c | A,B,C

那么在这种数据格式中,a&1逻辑相关,b&2等

我想使用 STRING_SPLIT 来拆分这些列,但是使用它两次显然会使它们相互交叉,导致总共有 9 行。

1 | a | A
1 | b | A    
1 | c | A    
1 | a | B    
1 | b | B    
1 | c | B    
1 | a | C
1 | b | C    
1 | c | C

我想要的只是 3 个“逻辑相关”的列

1 | a | A
1 | b | B
1 | c | C

但是,STRING_SPLIT(myCol,',') 似乎没有在任何地方保存字符串位置。

我做了以下事情:

SELECT tbl.ID,
      t1.Column1Value,
      t2.Column2Value
FROM myTable tbl
INNER JOIN (
   SELECT t.ID, 
       ss.value AS Column1Value, 
       ROW_NUMBER() OVER (PARTITION BY t.ID ORDER BY t.ID) as StringOrder
   FROM myTable t
   CROSS APPLY STRING_SPLIT(t.column1,',') ss
) t1 ON tbl.ID = t1.ID
INNER JOIN (
   SELECT t.ID, 
       ss.value AS Column2Value, 
       ROW_NUMBER() OVER (PARTITION BY t.ID ORDER BY t.ID) as StringOrder
   FROM myTable t
   CROSS APPLY STRING_SPLIT(t.column2,',') ss
) t1 ON tbl.ID = t2.ID AND t1.StringOrder = t2.StringOrder

这似乎适用于我的小型测试集,但在我看来,没有理由期望它每次都能保证有效。 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) 显然是无意义的排序,但看起来,在没有任何实际排序的情况下,STRING_SPLIT 正在返回“默认”顺序中的值他们已经进去了。这是“预期的”行为吗?我可以指望这个吗?有没有其他方法可以完成我想要做的事情?

谢谢。

======================

编辑

我通过以下 UDF 得到了我想要的(我认为)。但是它很慢。有什么建议吗?

CREATE FUNCTION fn.f_StringSplit(@string VARCHAR(MAX),@delimiter VARCHAR(1))
RETURNS @r TABLE
(
    Position INT,
    String VARCHAR(255)
)
AS
BEGIN

    DECLARE @current_position INT
    SET @current_position = 1

    WHILE CHARINDEX(@delimiter,@string) > 0 BEGIN

        INSERT INTO @r (Position,String) VALUES (@current_position, SUBSTRING(@string,1,CHARINDEX(@delimiter,@string) - 1))

        SET @current_position = @current_position + 1
        SET @string = SUBSTRING(@string,CHARINDEX(@delimiter,@string) + 1, LEN(@string) - CHARINDEX(@delimiter,@string))

    END

    --add the last one
    INSERT INTO @r (Position, String) VALUES(@current_position,@string)

    RETURN
END

最佳答案

我发现唯一能明确维护 String_Split() 函数顺序的方法是使用 Row_Number() 函数,在“订购方式”。

例如:

declare @Version nvarchar(128)
set @Version = '1.2.3';

with V as (select value v, Row_Number() over (order by (select 0)) n from String_Split(@Version, '.'))
    select
        (select v from V where n = 1) Major,
        (select v from V where n = 2) Minor,
        (select v from V where n = 3) Revision

返回:

Major Minor Revision
----- ----- ---------
1     2     3        

更新:如果您使用的是较新版本的 SQL Server,您现在可以提供一个可选的第三位参数,指示结果中也应包含序号列。有关更多详细信息,请在此处查看我的其他答案。

关于SQL - STRING_SPLIT 字符串位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48756012/

相关文章:

sql-server - DBContext SaveChanges 在内部是如何工作的?

php - 选择第二、第三、第四、第五最大的数

PHP Cookie 安全问题

sql - 用于范围查找的快速表索引

java - com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException : error in SQL syntax

sql-server - T-SQL 使用 XPath 查询 XML 列非常慢 - 如何改进或替代?

sql - 尝试使用 SQL 查询获取公共(public)交通的直接、间接、相交路线

sql-server - 通过Powershell将文本加载到SQL Server中

sql-server - 如何在两个docker容器(mssql和.net core应用程序)之间进行通信连接被拒绝127.0.0.1 :1433

mysql - 搜索多个值 - SQL