我知道这个问题已被问到很多,因为我无法找到合适的解决方案。
我有一个字符串的变体:
VALA |值Valb | 1 | val1a | Val1b | Val2a | Val2b | Val3a | Val3b
第3个元素介于0和3之间,并显示ValNa
和ValNb
之后的数量。当它为0时,之后没有元素。如果为1,则只有1个元素位于其后面(Val1a
和Val1b
)。
我需要TSQL选择将每个元素作为列返回。例如:
SELECT valA,valB,1,val1a,Val1b
我不能使用PARSENAME
因为它最多允许4个元素
以下是我所有组合的示例:
VALA |值Valb | 0
VALA |值Valb | 1 | val1a | Val1b
VALA |值Valb | 2 | val1a | Val1b | Val2a | Val2b
VALA |值Valb | 3 | val1a | Val1b | Val2a | Val2b | Val3a | Val3b
现在我正在使用此解决方案,但我无法管理最终元素:
DECLARE @param AS VARCHAR(MAX) = 'valA|ValB|2|val1a|val1b|val2a|val2b';
DECLARE @delimiter AS CHAR(1) = '|';
SELECT a FROM (VALUES (@param + @delimiter)) AS MyTable(a);
SELECT
CASE WHEN P1.Pos>0 THEN LEFT(Prm,P1.Pos-1) ELSE '' END AS valA,
CASE WHEN P2.Pos>0 THEN SUBSTRING (Prm, P1.Pos + 1, P2.Pos - P1.Pos - 1) ELSE '' END AS valB,
CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END AS Num,
CASE WHEN (P4.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END >= 1) THEN SUBSTRING (Prm, P3.Pos + 1, P4.Pos - P3.Pos - 1) ELSE '' END AS val1a,
CASE WHEN (P5.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END >= 1) THEN SUBSTRING (Prm, P4.Pos + 1, P5.Pos - P4.Pos - 1) ELSE '' END AS val1b,
CASE WHEN (P6.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END >= 2) THEN SUBSTRING (Prm, P5.Pos + 1, P6.Pos - P5.Pos - 1) ELSE '' END AS val2a,
CASE WHEN (P7.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END >= 2) THEN SUBSTRING (Prm, P6.Pos + 1, P7.Pos - P6.Pos - 1) ELSE '' END AS val2b,
CASE WHEN (P8.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END = 3) THEN SUBSTRING (Prm, P7.Pos + 1, P8.Pos - P7.Pos - 1) ELSE '' END AS val3a,
CASE WHEN (P9.Pos>0) AND (CASE WHEN P3.Pos>0 THEN SUBSTRING (Prm, P2.Pos + 1, P3.Pos - P2.Pos - 1) ELSE 0 END = 3) THEN SUBSTRING (Prm, P8.Pos + 1, P9.Pos - P8.Pos - 1) ELSE '' END AS val3b
FROM
(VALUES (@param + @delimiter)) AS baseTable(Prm)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param))) as P1(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P1.Pos+1))) as P2(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P2.Pos+1))) as P3(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P3.Pos+1))) as P4(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P4.Pos+1))) as P5(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P5.Pos+1))) as P6(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P6.Pos+1))) as P7(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P7.Pos+1))) as P8(Pos)
CROSS APPLY (SELECT (CHARINDEX(@delimiter, @param, P8.Pos+1))) as P9(Pos)
编辑:
我需要一种防弹解决方案,所以即使我的字符串为空,SQL也只返回空值。
请谁投票支持我的问题,你能否只是评论为什么?所以我可以记下来,不要再犯同样的错误。
答案 0 :(得分:4)
DECLARE @t TABLE (Value VARCHAR(8000))
INSERT INTO @t VALUES
('valA|valB|0'),
('valA|valB|1|val1a|Val1b'),
('valA|valB|2|val1a|Val1b|Val2a|Val2b'),
('valA|valB|3|val1a|Val1b|Val2a|Val2b|Val3a|Val3b')
;WITH Split_Fields (Field, xmlfields)
AS
(
SELECT Value AS Field,
CONVERT(XML,'<Fields><field>'
+ REPLACE(Value,'|', '</field><field>') + '</field></Fields>') AS xmlfields
FROM @t
)
SELECT Field
,xmlfields.value('/Fields[1]/field[1]','varchar(100)') AS Field1
,xmlfields.value('/Fields[1]/field[2]','varchar(100)') AS Field2
,xmlfields.value('/Fields[1]/field[3]','varchar(100)') AS Field3
,xmlfields.value('/Fields[1]/field[4]','varchar(100)') AS Field4
,xmlfields.value('/Fields[1]/field[5]','varchar(100)') AS Field5
,xmlfields.value('/Fields[1]/field[6]','varchar(100)') AS Field6
,xmlfields.value('/Fields[1]/field[7]','varchar(100)') AS Field7
,xmlfields.value('/Fields[1]/field[8]','varchar(100)') AS Field8
,xmlfields.value('/Fields[1]/field[9]','varchar(100)') AS Field9
,xmlfields.value('/Fields[1]/field[10]','varchar(100)') AS Field10
FROM Split_Fields
╔═════════════════════════════════════════════════╦════════╦════════╦════════╦════════╦════════╦════════╦════════╦════════╦════════╦═════════╗
║ Field ║ Field1 ║ Field2 ║ Field3 ║ Field4 ║ Field5 ║ Field6 ║ Field7 ║ Field8 ║ Field9 ║ Field10 ║
╠═════════════════════════════════════════════════╬════════╬════════╬════════╬════════╬════════╬════════╬════════╬════════╬════════╬═════════╣
║ valA|valB|0 ║ valA ║ valB ║ 0 ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
║ valA|valB|1|val1a|Val1b ║ valA ║ valB ║ 1 ║ val1a ║ Val1b ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
║ valA|valB|2|val1a|Val1b|Val2a|Val2b ║ valA ║ valB ║ 2 ║ val1a ║ Val1b ║ Val2a ║ Val2b ║ NULL ║ NULL ║ NULL ║
║ valA|valB|3|val1a|Val1b|Val2a|Val2b|Val3a|Val3b ║ valA ║ valB ║ 3 ║ val1a ║ Val1b ║ Val2a ║ Val2b ║ Val3a ║ Val3b ║ NULL ║
╚═════════════════════════════════════════════════╩════════╩════════╩════════╩════════╩════════╩════════╩════════╩════════╩════════╩═════════╝