【问题标题】:How to update a column base on another column's value from another table?如何根据另一个表中另一列的值更新列?
【发布时间】:2019-08-20 02:19:11
【问题描述】:

我有一个table A,有 2 个主要列:NameSettingsSettings 列将有 3 个值:1、2 或 3。

例如:

Name     Settings
Andre        1
Andre        1
Betty        3
Charles      1
Charles      1

注意1个Name只能有1个Settings:1、2或3

我还有另一个 table B,有 2 个主要列:NameTypeType 列包含 3 个值:'TypeA''TypeB''TypeC'

例如:

Name       Type
Andre      TypeA
Andre      TypeA
Andre      TypeC
Betty      TypeB
Betty      TypeB
Charles    TypeB
Charles    TypeA
Charles    TypeA

请注意,1 个Name 可以有多个相同或不同的Type。我们不考虑TypeC,只考虑TypeATypeB

现在我想使用来自table B'Type' 列从table A 更新Settings 列,如果:

  • table B 中的Type 列的值为'TypeA',然后将两个表中具有相同Name 的所有记录设置为来自Settings 列的Settings 1 @。
  • table B 中的Type 列的值为'TypeB',然后将两个表中具有相同Name 的所有记录设置为来自@987654356 的Settings 列上的2 @。
  • table B 中的Type 列同时具有'TypeA''TypeB' 的值,然后将两个表中具有相同Name 的所有记录设置为@ 上的3 987654362@ 列来自table A

table A 的结果会变成这样:

Name     Settings
Andre        1
Andre        1
Andre        1
Betty        2
Charles      3
Charles      3

【问题讨论】:

    标签: sql sql-server tsql sql-update


    【解决方案1】:

    一种方法是聚合JOINing之前的第二张表:

    UPDATE a
        SET settings = (CASE WHEN num_a > 0 AND num_b = 0 THEN 1
                             WHEN num_b > 0 THEN 2
                             ELSE 3
                        END)
    FROM tablsA a JOIN
         (SELECT b.name,
                 SUM(CASE WHEN type = 'TypeA' THEN 1 ELSE 0 END) as num_a,
                 SUM(CASE WHEN type = 'TypeB' THEN 1 ELSE 0 END) as num_B
          FROM tableB b
          GROUP BY b.name
         ) b
         ON a.name = b.name
    

    【讨论】:

      【解决方案2】:

      在这种情况下,我看到了多个选项。

      您可以考虑规范化这些表并通过级联更新添加外键。

      您可以将其中一个表替换为视图并映射值;这取决于可以更新哪个表。如果两者都接收更新,则此解决方案可能仅在您使用索引视图时才有效。

      如果您在不同类型上有不同或重叠的设置,也可能与用户的依赖关系有关,您可能需要一个映射表来将类型映射到设置。

      也可以为这些事情使用触发器以确保一致性,但您应该更喜欢具有正确外键的适当表布局。

      提供有关您的用例的更多详细信息也可能会有所帮助。

      【讨论】:

        【解决方案3】:

        听起来你需要一个更新连接语句:

        UPDATE a
        SET    settings = CASE type WHEN 'TypeA' THEN 1
                                    WHEN 'TypeB' THEN 2
                          END
        FROM   tablsA a
        JOIN   tableB b ON a.name = b.name
        WHERE  type IN ('TypeA', 'TypeB') -- just a precaution
        

        【讨论】:

        • 非常需要的预防措施,否则当您没有添加 where 子句时,其他(非匹配)类型将被更新为 NULL..
        • @RaymondNijland 是的,这就是它存在的原因。从 OP 的描述来看,目前尚不清楚表中是否确实存在其他类型。不过。
        • 确实,我仍然会在 case 子句中添加 ELSE type = type 作为额外的安全网,以应对 WHERE 子句和 CASE 语句不匹配的情况,在编写大型查询时可能会发生这种情况。但仍然谁会在生产数据库上执行这些类型的查询而不在生产数据库的一个小副本上进行测试作为测试
        • @Mureinik 你说得对,“类型”列中有更多值,但我只考虑“类型A”和“类型B”作为我的查询。还有另一个条件我忘了添加,只是编辑了问题。无论如何谢谢:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-17
        • 2011-11-25
        • 2017-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多