2017-04-19 86 views
0

如果在给定列中存在任何特定值(本例中为'[#]'),我需要获取3个相似的行数据集替换列值。例如根据列值将单行分割成更多列

--------------------- 
Type  Value 
--------------------- 
1  Apple[#] 
2  Orange 
3  Peach[#] 

我需要修改查询来获取值,如下

---------------------- 
    Type  Value 
-------------------- 
    1   Apple1 
    1   Apple2 
    1   Apple3 
    2   Orange 
    3   Peach1 
    3   Peach2 
    3   Peach3 

我不能想出逻辑如何得到这个

+0

如何你认识你吗?想要3个苹果和3个桃子,但只有1个桔子? – jarlh

+0

它基于列中存在的'#'符号。我忘了提及 –

+0

所以如果有[#],那么你总是想要3,否则1? –

回答

1

您也可以不用递归性相同的结果:

select Type, Value from MyTable where Right(Value, 3) <> '[#]' 
union 
select Type, Replace(Value, '[#]', '1') from MyTable where Right(Value, 3) = '[#]' 
union 
select Type, Replace(Value, '[#]', '2') from MyTable where Right(Value, 3) = '[#]' 
union 
select Type, Replace(Value, '[#]', '3') from MyTable where Right(Value, 3) = '[#]' 

order by 1, 2 
+0

谢谢,这工作。这是一个非常简单易懂的解决方案。 –

1

假设只存在一个数字(如在你的例子中),那么我会去:

with cte as (
     select (case when value like '%\[%%' then left(right(value, 2), 1) + 0 
        else 1 
       end) as cnt, 1 as n, 
      left(value, charindex('[', value + '[')) as base, type 
     from t 
     union all 
     select cnt, n + 1, base, type 
     from cte 
     where n + 1 <= cnt 
    ) 
select type, 
     (case when cnt = 1 then base else concat(base, n) end) as value 
from cte; 

当然,CTE可以很容易地扩展到数字y个:

(case when value like '%\[%%' 
     then stuff(left(value, charindex(']')), 1, charindex(value, '['), '') + 0 
     else 1 
end) 

一旦你有多少,你可以使用数字的另一个来源。但递归CTE似乎是问题中特定问题的最简单解决方案。

0

尝试此查询

DECLARE @SampleData AS TABLE 
(
    Type int, 
    Value varchar(100) 
) 

INSERT INTO @SampleData 
VALUES (1, 'Apple[#]'), (2, 'Orange'), (3, 'Peach[#]') 

SELECT sd.Type, cr.Value 
FROM @SampleData sd 
CROSS APPLY 
(
    SELECT TOP (IIF(Charindex('[#]', sd.Value) > 0, 3, 1)) 
      x.[Value] + Cast(v.t as nvarchar(5)) as Value 
    FROM 
     (SELECT Replace(sd.Value, '[#]', '') AS Value) x 
     Cross JOIN (VALUES (1),(2),(3)) v(t) 
    Order by v.t asc 

) cr 

演示链接:Rextester

0

使用递归CTE

CREATE TABLE #test 
(
    Type int, 
    Value varchar(50) 
) 

INSERT INTO #test VALUES 
(1, 'Apple[#]'), 
(2, 'Orange'), 
(3, 'Peach[#]'); 

WITH CTE AS (
    SELECT 
     Type, 
     IIF(RIGHT(Value, 3) = '[#]', LEFT(Value, LEN(Value) - 3), Value) AS 'Value', 
     IIF(RIGHT(Value, 3) = '[#]', 1, NULL) AS 'Counter' 
    FROM 
     #test 
    UNION ALL 
    SELECT 
     B.Type, 
     LEFT(B.Value, LEN(B.Value) - 3) AS 'Value', 
     Counter + 1 
    FROM 
     #test AS B 
     JOIN CTE 
      ON B.Type = CTE.Type 
    WHERE 
     RIGHT(B.Value, 3) = '[#]' 
     AND Counter < 3 
) 

SELECT 
    Type, 
    CONCAT(Value, Counter) AS 'Value' 
FROM 
    CTE 
ORDER BY 
    Type, 
    Value 

DROP TABLE #test