我有一个包含两列逗号分隔字符串的表格。数据格式化的方式,两列中逗号分隔的项目数相等,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/