WITH CTE 和大型 UNION 查询的替代方法
Alternate approach to WITH CTE and large UNION query
我想修改我收到的剧本。
它目前的工作方式是通过使用大量 UNION 的 WITH CTE。
当前设置
我们从源 table 获取一条记录,使用 [Name] A 将其插入目标 table 一次,然后使用 [Name] B 再次插入它。本质上是创建多行在目的地,尽管 [Name].
不同
一个事务的示例是从 [Source] 中获取此行:
ID [123] Name [Red and Green]
我目前在[Destination]设置的结果是:
ID [123] Name [Red]
ID [123] Name [Green]
当前逻辑
这是当前逻辑的简化版本:
WITH CTE
AS
(SELECT ID,
'Red' AS [Name]
FROM [Source_Table]
WHERE [Name] = 'Red and Green'
UNION ALL
SELECT ID,
'Green' AS [Name]
FROM [Source_Table]
WHERE [Name] = 'Red and Green')
INSERT INTO [Destination_Table]
(ID,
[Name])
SELECT ID,
[Name]
FROM CTE;
我想返工的原因是当我们得到一个新的 [Name] 时,我们必须手动将另一部分代码添加到我们的(不断增加的)UNION 中,以确保它被拾取。
我考虑过的
我考虑的是在控件 table 之外设置一个 WHILE LOOP(或 CURSOR)运行,我们可以在其中存储所有 [Names]。但是,我不确定这是否是最好的方法,而且我还不太熟悉 LOOPS/CURSORS。此外,一旦所有 [Name] 完成,我也不太确定如何停止循环。
非常感谢任何帮助。
引入一个名为 Color_List 的新 table,其中每种可能的颜色只包含一行。然后这样做:
with cte as
(
select
st.ID,
c.colorname
from
Source_Table s
inner join
Color_List c
on
CHARINDEX(c.colorname, s.[Name]) > 0
)
insert into Destination_Table
(
ID,
[Name]
)
select
ID,
colorname
from
cte
此方法的好处是您 hard-coding 查询中没有任何颜色名称。 Color_List table.
中维护所有颜色名称(并且可能有两个以上的颜色名称)
您可以使用 cross apply
来复制行:
insert into [destination_table] (id, name)
select x.*
from source_table s
cross apply (values (id, 'Red'), (id, 'Green')) x(id, name)
where name = 'Red and Green'
您可以使用 string_split 将值分开。首先用竖线“|”替换“和”。然后在垂直管道上做一个字符串拆分。
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1, '[123]', 'Name', '[Red and Green]')) V(ID, testCol, nameCol, stringCol);
select ID, testCol, nameCol,
case when left([value], 1)!='[' then concat('[',[value]) else
case when right([value], 1)!=']' then concat([value], ']') else [value] end end valCol
from #tTEST t
cross apply string_split(replace(t.stringCol, ' and ', '|'), '|');
结果
ID testCol nameCol valCol
1 [123] Name [Red]
1 [123] Name [Green]
我想修改我收到的剧本。
它目前的工作方式是通过使用大量 UNION 的 WITH CTE。
当前设置
我们从源 table 获取一条记录,使用 [Name] A 将其插入目标 table 一次,然后使用 [Name] B 再次插入它。本质上是创建多行在目的地,尽管 [Name].
不同一个事务的示例是从 [Source] 中获取此行:
ID [123] Name [Red and Green]
我目前在[Destination]设置的结果是:
ID [123] Name [Red]
ID [123] Name [Green]
当前逻辑
这是当前逻辑的简化版本:
WITH CTE
AS
(SELECT ID,
'Red' AS [Name]
FROM [Source_Table]
WHERE [Name] = 'Red and Green'
UNION ALL
SELECT ID,
'Green' AS [Name]
FROM [Source_Table]
WHERE [Name] = 'Red and Green')
INSERT INTO [Destination_Table]
(ID,
[Name])
SELECT ID,
[Name]
FROM CTE;
我想返工的原因是当我们得到一个新的 [Name] 时,我们必须手动将另一部分代码添加到我们的(不断增加的)UNION 中,以确保它被拾取。
我考虑过的
我考虑的是在控件 table 之外设置一个 WHILE LOOP(或 CURSOR)运行,我们可以在其中存储所有 [Names]。但是,我不确定这是否是最好的方法,而且我还不太熟悉 LOOPS/CURSORS。此外,一旦所有 [Name] 完成,我也不太确定如何停止循环。
非常感谢任何帮助。
引入一个名为 Color_List 的新 table,其中每种可能的颜色只包含一行。然后这样做:
with cte as
(
select
st.ID,
c.colorname
from
Source_Table s
inner join
Color_List c
on
CHARINDEX(c.colorname, s.[Name]) > 0
)
insert into Destination_Table
(
ID,
[Name]
)
select
ID,
colorname
from
cte
此方法的好处是您 hard-coding 查询中没有任何颜色名称。 Color_List table.
中维护所有颜色名称(并且可能有两个以上的颜色名称)您可以使用 cross apply
来复制行:
insert into [destination_table] (id, name)
select x.*
from source_table s
cross apply (values (id, 'Red'), (id, 'Green')) x(id, name)
where name = 'Red and Green'
您可以使用 string_split 将值分开。首先用竖线“|”替换“和”。然后在垂直管道上做一个字符串拆分。
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1, '[123]', 'Name', '[Red and Green]')) V(ID, testCol, nameCol, stringCol);
select ID, testCol, nameCol,
case when left([value], 1)!='[' then concat('[',[value]) else
case when right([value], 1)!=']' then concat([value], ']') else [value] end end valCol
from #tTEST t
cross apply string_split(replace(t.stringCol, ' and ', '|'), '|');
结果
ID testCol nameCol valCol
1 [123] Name [Red]
1 [123] Name [Green]