【问题标题】:Alternate approach to WITH CTE and large UNION queryWITH CTE 和大型 UNION 查询的替代方法
【发布时间】:2020-09-03 14:34:26
【问题描述】:

我想重新编写我收到的脚本。

它目前的工作方式是通过使用大量 UNION 的 WITH CTE。

当前设置

我们从源表中取出一条记录,用 [Name] A 将其插入目标表一次,然后用 [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 中,以确保它被拾取。

我的考虑

我正在考虑设置一个运行控制表的 WHILE LOOP(或 CURSOR),我们可以在其中存储所有 [Names]。但是,我不确定这是否是最好的方法,而且我对 LOOPS/CURSORS 还不太熟悉。此外,一旦完成所有 [Name],就不太确定如何停止循环。

非常感谢任何帮助。

【问题讨论】:

  • 请勿发布代码图片。代码是文本,应该张贴在代码围栏中。

标签: sql sql-server database tsql sql-insert


【解决方案1】:

您可以使用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'

【讨论】:

    【解决方案2】:

    引入一个名为 Color_List 的新表,它只包含每个可能颜色的一行。然后这样做:

    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
    

    此方法的好处是您无需在查询中对任何颜色名称进行硬编码。所有颜色名称(可能不止两个)都保存在 Color_List 表中。

    【讨论】:

    • 谢谢。我选择使用它,因为它看起来相当简单,而且我喜欢有一个单独的控制表的想法。
    【解决方案3】:

    您可以使用 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]
    

    【讨论】:

      猜你喜欢
      • 2013-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多