我有一张这样的表
Col1 Col2
Adam 1
Barbara, Catherina 1
Barbara, Catherina 2
Adam, Catherina 1
Adam, Catherina 2
Barbara, Adam, Daniela 1
Barbara, Adam, Daniela 2
Barbara, Adam, Daniela 3
需要一个select语句来填充Col3,如下所示
Col1 Col2 Col 3
Adam 1 Adam
Barbara, Catherina 1 Barbara
Barbara, Catherina 2 Catherina
Adam, Catherina 1 Adam
Adam, Catherina 2 Catherina
Barbara, Adam, Daniela 1 Barbara
Barbara, Adam, Daniela 2 Adam
Barbara, Adam, Daniela 3 Daniela
我尝试过使用SUBSTRING& CHARINDEX但无法解决问题。需要一个SQL,我们可以传递Col2值并填充Col3。
请帮忙。 谢谢你,维克拉姆
答案 0 :(得分:3)
使用Parse / Split功能和Cross Apply。
我应该补充一点,如果你不能使用或不想要UDF,那么解析可以很容易地迁移到CROSS APPLY中。
Declare @YourTable table (Col1 varchar(25),Col2 int)
Insert Into @YourTable Values
('A', 1),
('B,C', 1),
('B,C', 2),
('A,C', 1),
('A,C', 2),
('B,A,D', 1),
('B,A,D', 2),
('B,A,D', 3)
Select A.*
,Col3 = B.RetVal
From @YourTable A
Cross Apply (Select * from [dbo].[udf-Str-Parse](A.Col1,',') where RetSeq=A.Col2) B
返回
Col1 Col2 Col3
A 1 A
B,C 1 B
B,C 2 C
A,C 1 A
A,C 2 C
B,A,D 1 B
B,A,D 2 A
B,A,D 3 D
UDF(如果需要)
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
只是为了好玩,这是NON-UDF版本
Select A.*
,Col3 = B.RetVal
From @YourTable A
Cross Apply (
Select * From(
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(A.Col1,',','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) C where RetSeq=A.Col2
) B
答案 1 :(得分:1)
此版仅适用于SQL 2016和Azure SQL DB(more on STRING_SPLIT)
DECLARE @DaTable TABLE (Col1 varchar(32),Col2 int)
INSERT INTO @DaTable
VALUES
('A', 1),
('B,C', 1),
('B,C', 2),
('A,C', 1),
('A,C', 2),
('B,A,D', 1),
('B,A,D', 2),
('B,A,D', 3)
SELECT S.*
,Col3 = T.Value
From @DaTable S
Cross Apply (SELECT * FROM
(Select Value, Row_Number() OVER (ORDER BY (SELECT 0)) AS RowNum from STRING_SPLIT(S.Col1,',')) AS ss
where ss.RowNum = S.Col2) AS T
Azure SQL DB注意事项:
STRING_SPLIT功能仅在兼容级别130下可用。[...] 请注意,即使在新的Azure SQL数据库中,兼容级别120也可能是默认的。
答案 2 :(得分:-1)
您可以创建一个获取字符串(col1
)和文本索引(col2
)的函数,并返回正确的值。查询将如下所示:
SELECT col1, col2, GetElement(co1, col2) as col3
FROM table
GetElement
可以使用WHILE
循环来查找值。伪代码:
index = 1
while index < col2
charindex of the ','
if index == col2 substring to the next ',' and return
else index = index + 1 and remove the substring from beginning to the charindex of ','