Sql 基于列值将单行拆分为更多列

Sql 基于列值将单行拆分为更多列,sql,sql-server,database,tsql,Sql,Sql Server,Database,Tsql,在这种情况下,如果给定列“[]”中存在任何特定值,我需要获得3组类似的行数据来替换列值。比如说 --------------------- Type Value --------------------- 1 Apple[#] 2 Orange 3 Peach[#] 我需要修改查询以获得如下值 ---------------------- Type Value -------------------- 1

在这种情况下,如果给定列“[]”中存在任何特定值,我需要获得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

我想不出如何得到这个

的逻辑,假设只有一个数字,如您的示例所示,那么我会选择:

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似乎是问题中特定问题的最简单解决方案。

假设只有一个数字,如您的示例所示,那么我会选择:

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似乎是问题中特定问题的最简单解决方案。

试试这个查询

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
演示链接:

尝试此查询

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

演示链接:

您也可以在不使用递归的情况下获得相同的结果:

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

您也可以在不使用递归的情况下获得相同的结果:

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
使用递归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
使用递归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

你怎么知道你想要3个苹果和3个桃子,但只想要1个橘子?这是基于列中的符号。我忘了提到这一点,所以如果有[],那么您总是想要3,否则是1?如果有[],我想要3行类似的列,使用select语句动态地将值从1追加到3。如果[]不存在,我希望能够得到相同的结果。你知道你想要3个苹果和3个桃子,但只想要1个橙色吗?它基于列中存在的符号。我忘了提到这一点,所以如果有[],那么您总是想要3,否则是1?如果有[],我想要3行类似的列,使用select语句动态地将值从1追加到3。如果[]不存在,我希望能够得到相同的结果谢谢,这很有效。这是一个非常简单易懂的解决方案。谢谢,这很有效。这是一个非常简单易懂的解决方案。