【问题标题】:Update one table with the results from another用另一个表的结果更新一个表
【发布时间】:2015-02-04 08:53:32
【问题描述】:

我有一个包含 3 列(classID - INT、teacherID INT、isActive BOOLEAN)的 TABLE (Classes_Teachers)。

我读取了一个新文件的内容并创建了一个具有相同列但具有最新数据的表 (StudentsTemp),并希望将两者“合并”。

我可以使用 EXCEPT AND JOIN 轻松完成此操作,但是这将删除 StudentsTemp 中不存在的所有学生行,但是我需要能够将 isActive 设置为 false,因为我必须保留报告数据目的。

这是一个用于多对多关系的“JOIN”表,因此它没有单个主键。

例如

学生:

+----------------------------------+ | ClassID TeacherID isActive | +----------------------------------+ | 1 2 1 | | 1 12 1 | | 1 13 0 | | 5 10 1 | +----------------------------------+

学生的温度

+----------------------------------+ | ClassID TeacherID isActive | +----------------------------------+ | 1 2 1 | | 1 13 1 | | 1 6 1 | +----------------------------------+

在这种情况下,第 5 班不再由教师 10 教授,因此该条目通常会被“删除”,但我只想将“isActive”更改为 0

第 1 课也不再由教师 12 教授,因此这应该将 isActive 更改为 0。

第 1 班现在由 13 号老师代替; ie 现在是“活动的”,所以这会将 isActive 更改为 1

最后,有一个全新的教师 (id = 6),他教授的 classID 为 1,所以这会按原样插入行。

我需要学生像这样结束:

+----------------------------------+ | ClassID TeacherID isActive | +----------------------------------+ | 1 2 1 | | 1 12 0 | | 1 13 1 | | 5 10 0 | | 1 6 1 | +----------------------------------+

我可以通过创建 3 个临时表并使用 EXCEPT AND JOIN 来使用“删除”、“更改”和“插入”填充这些表,然后对它们运行 UPDATE AND INSERT 来做到这一点,但我想知道是否有无需创建 3 个额外的临时表即可更轻松地执行此操作。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    首先,插入新的teacherIDclassID 组合。然后更新 Students 表中的行。

    CREATE TABLE #Students(
        ClassID     INT,
        TeachedID   INT,
        isActive    BIT
    )
    CREATE TABLE #StudentsTemp(
        ClassID     INT,
        TeachedID   INT,
        isActive    BIT
    )
    INSERT INTO #Students VALUES
    (1, 2, 1), (1, 12, 1), (1, 13, 0), (5, 10, 1);
    INSERT INTO #StudentsTemp VALUES
    (1, 2, 1), (1, 13, 1), (1, 6, 1);
    
    
    UPDATE s
        SET s.isActive = ISNULL(t.isActive, 0)
    FROM #Students s
    LEFT JOIN #StudentsTemp t
        ON t.ClassID = s.ClassID
        AND t.TeachedID = s.TeachedID
    
    INSERT INTO #Students
    SELECT
        ClassID,
        TeachedID,
        isActive
    FROM #StudentsTemp t
    WHERE
        NOT EXISTS(
            SELECT 1
            FROM #Students
            WHERE
                ClassID = t.ClassID
                AND TeachedID = t.TeachedID
        )
    
    
    SELECT * FROM #Students
    
    DROP TABLE #Students
    DROP TABLE #StudentsTemp
    

    结果

    ClassID     TeachedID   isActive
    ----------- ----------- --------
    1           2           1
    1           12          0
    1           13          1
    5           10          0
    1           6           1
    

    【讨论】:

    • 非常感谢您。我真的很挣扎,你在半小时内为我修好了。这和@JonC 的工作绝对完美。是否有任何边缘情况,你能想到的问题,我在选择使用哪个时需要考虑
    • 选择您更了解的内容,以便在出现问题时知道从哪里查看。
    【解决方案2】:

    您是否尝试过使用 Merge 语句?

    https://msdn.microsoft.com/en-us/library/bb510625.aspx

    【讨论】:

      【解决方案3】:

      试试这样的:

      MERGE Students AS T
      USING Students_Temp AS S
      ON (T.ClassId = S.ClassID AND T.TeacherID = S.TeacherID) 
      WHEN NOT MATCHED BY TARGET
          THEN INSERT(ClassID, TeacherID, IsActive) VALUES(S.ClassID, S.TeacherID, S.IsActive)
      WHEN NOT MATCHED BY SOURCE
          THEN UPDATE SET T.IsActive = 0
      WHEN MATCHED 
          THEN UPDATE SET T.IsActive = S.IsActive
      

      【讨论】:

      • 非常感谢您。我真的很挣扎,你在半小时内为我修好了。这和@wewestthemenace 的工作都非常完美。是否有任何边缘情况,你能想到的问题,我在选择使用哪个时需要考虑
      • 嗯,MERGE 是 SQL Server 中一个非常酷的指令,用于在“单个语句”中处理插入-更新-删除,尽管 SQL Server 可能在后台执行类似于@wewestthemenace 的解决方案的操作。报告了一些性能问题以及何时涉及触发器,但在您的情况下,我没有看到使用它的潜在问题。在这里mssqltips.com/sqlservertip/3074/…你可以找到一些关于 MERGE 语句的相关问题的信息。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 2016-12-19
      • 1970-01-01
      • 2013-02-15
      相关资源
      最近更新 更多