【问题标题】:Optimize a case expression优化案例表达式
【发布时间】:2020-05-21 01:54:54
【问题描述】:

我有一长串:

update wi
   SET class
   case
        WHEN wi.column = 'a' THEN (select top 1 from lookup_tbl1  where code = 1)
        WHEN wi.column = 'b' THEN (select top 1 from lookup_tbl1  where code = 2)
        WHEN wi.column = 'c' THEN (select top 1 from lookup_tbl1  where code = 3)
        WHEN wi.column = 'd' THEN (select top 1 from lookup_tbl1  where code = 80)

   end
   SET name
   case
        WHEN wi.column2 = 'Chris' THEN (select top 1 from table1  where code = 1)
        WHEN wi.column2 = 'david' THEN (select top 1 from table1  where code = 2)
        WHEN wi.column2 = 'tan' THEN (select top 1 from table1  where code = 3)
        WHEN wi.column2 = 'drake' THEN (select top 1 from table1  where code = 80)
        WHEN wi.column2 = 'x' THEN ..........

   end
   SET department
   case
        WHEN wi.column3 like 'd.d%' then 'Director D'
        WHEN wi.column3 like '%AC'  then  'Accounting'

   end

FROM transform_tbl wi WHERE flag is null

我正在清理 transform_tbl 表。我需要用实际名称替换缩写并修复该表中的数据。 还有其他方法或更好的方法吗?

【问题讨论】:

  • 它实际上被称为 case 表达式——正是因为它不是一个语句。
  • 您需要包含一些外部语句,以便我们可以看到列来自哪里以及涉及哪些其他表。
  • 请显示完整的查询和数据结构
  • 您的查询在语法上不正确,因为子查询需要选择某些内容。这也有助于查看查询的其余部分。并了解为什么您使用 top 而不使用 order by
  • 我在问题中添加了更多细节。 @DaleK

标签: sql sql-server tsql sql-update subquery


【解决方案1】:

您可以将case 移动到子查询中,如下所示:

(
    select top (1) col
    from table1
    where code = case column
        when 'a' then 1
        when 'b' then 2
        when 'c' then 3
        when 'd' then 80
    end
)

注意事项:

  • 您的子查询在select 子句中缺少实际列;我假设col

  • 可能会进行进一步优化,但您需要向我们展示您的整个查询,并解释其意图 - 您可能想为此提出一个新问题

【讨论】:

  • @user7331796 实际上这个答案向您展示了如何做到这一点,只需用这个替换每个列更新。
【解决方案2】:

如果你在table1(code) 上有一个索引,你的方法可能没问题。好吧,这与它在语法上不正确的事实不同。子查询需要选择一些东西。

也就是说,我会重组代码,这样codecolumn 之间就没有什么神奇的对应关系了。例如,table1 可能应该包含标识行的字母。这将大大简化查询:

(select top (1) ? from table1 t1 where t1.letter = ?.column)

不需要case 表达式。

【讨论】:

    【解决方案3】:

    最好的选择是为此创建一个单独的表,它可以将column 值映射到code 值,可能带有索引。然后你可以加入它而不需要复杂的case 表达式。

    但如果做不到这一点,您可以使用 table value constructor 创建映射:

    INNER JOIN (VALUES 
        ('a', 1), 
        ('b', 2), 
        ('c', 3),
        ('d', 80),
        ('x', ... )   
    ) AS map(col, code) ON map.col = [column]
    INNER JOIN table1 ON table1.code = map.code
    

    或者,给定top 1,您可能需要apply

    INNER JOIN (VALUES 
        ('a', 1), 
        ('b', 2), 
        ('c', 3),
        ('d', 80),
        ('x', ... )   
    ) AS map(col, code) ON map.col = column
    OUTER APPLY (SELECT TOP 1 ? FROM table1 WHERE table1.code = map.code) t1
    

    但正如在其他答案中所说,我们需要知道您要查找的列。

    最后,由于我们没有完整的原始查询,我无法确切告诉您如何将其与其余代码集成,甚至无法告诉您是否想要 INNERLEFT 加入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      相关资源
      最近更新 更多