存储过程比较两个表和 Insert/Update 值

Stored Procedure Compare Two Tables And Insert/Update Value

假设我有2个table: Table A, Table B

Table A

的示例记录
StuId ExamId Name Listening Writing Reading TotalMarks Status Remarks
S001 EX123 Amanda 70 85 88 81 (null) (null)
S002 EX150 Elisa 60 74 52 62 (null) (null)

Table B

的样本记录
StuId ExamId Name Listening Writing Reading TotalMarks
S001 EX123 Amanda 70 85 88 81
S002 EX150 Elisa 65 74 52 64
S003 EX213 Derick 80 78 92 83
S004 EX334 Jonathan 43 65 69 59

我想在存储过程中做的事情:

  1. 比较 StuId & ExamId 在 Table B 是否存在于 Table A?
    • 如果存在,将值插入到 Status = 'remain'
    • 如果不存在,则向TableB插入记录,并且Status = 'new'
  2. 比较Listening, Writing, Reading, TotalMarks的分数
    • 如果在Table A中标记与Table B相同,则将值插入Remarks = 'none'
    • 如果 Table A 中的 Listening 标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入Remarks = 'Ori lis % = ' + (来自 Table A 的标记) + '新列表 % = ' + (来自 Table B 的标记)
    • 如果 Table A 中的 Writing 标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value to Remarks = Remarks + 'Ori wri % = ' + (marks from Table A) + ' New wri % = ' + (marks from Table B)
    • 如果 Table A 中的 Reading 标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value to Remarks = Remarks + 'Ori rea % = ' + (marks from Table A) + ' New rea % = ' + (marks from Table B)
    • TotalMarks 相同

EXEC 存储过程后 Table A 的预期结果

StuId ExamId Name Listening Writing Reading TotalMarks Status Remarks
S001 EX123 Amanda 70 85 88 81 remain none
S002 EX150 Elisa 65 74 52 64 remain Ori lis % = 60 New list % = 65 Ori ttl % = 62 New ttl % = 64
S003 EX213 Derick 80 78 92 83 new none
S004 EX334 Jonathan 43 65 69 59 new none

我设法做到的:

代码:

DECLARE @StatusRem VARCHAR(20) = 'remain'
DECLARE @StatusNew VARCHAR(20) = 'new'
DECLARE @Remarks VARCHAR(100) = ' '

INSERT INTO Table_A (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)         
    SELECT 
        StuId, ExamId, Name, Listening, Writing, Reading,    
        TotalMarks, @StatusNew, @Remarks
    FROM 
        Table_B b 
    LEFT JOIN 
        table_A a ON b.StuId = a.StuId 
                  AND b.ExamId = a.ExamId
    WHERE 
        a.StuId IS NULL AND a.ExamId IS NULL

有人知道我应该如何继续插入 'remain' 状态、比较和更新标记并插入备注吗?

感谢您的帮助!

为了讨论和演示,我们必须有表格,而不是关于表格的故事。下次您应该发布查询以创建表并插入示例数据,如下所示

-- DDL+DML
use tempdb
GO

DROP TABLE IF EXISTS TA
GO

CREATE TABLE TA (
    StuId        NVARCHAR(100),
    ExamId       NVARCHAR(100),
    Name         NVARCHAR(100),
    Listening    INT          ,
    Writing      INT          ,
    Reading      INT          ,
    TotalMarks   INT          ,
    Status       NVARCHAR(100),
    Remarks      NVARCHAR(MAX)
)
GO

INSERT TA (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)
VALUES
('S001', 'EX123', 'Amanda', 70, 85, 88, 81, null, null),
('S002', 'EX150', 'Elisa' , 60, 74, 52, 62, null, null)
GO

DROP TABLE IF EXISTS TB
GO

CREATE TABLE TB (
    StuId        NVARCHAR(100),
    ExamId       NVARCHAR(100),
    Name         NVARCHAR(100),
    Listening    INT          ,
    Writing      INT          ,
    Reading      INT          ,
    TotalMarks   INT          
)
GO

INSERT TB (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks)
VALUES
('S001', 'EX123', 'Amanda'  , 70, 85, 88, 81),
('S002', 'EX150', 'Elisa'   , 65, 74, 52, 64),
('S003', 'EX213', 'Derick'  , 80, 78, 92, 83),
('S004', 'EX334', 'Jonathan', 43, 65, 69, 59)
GO

SELECT * FROM TA
SELECT * FROM TB
GO

现在我们可以开始讨论并提出解决方案

1.Compare StuId & ExamId in Table B exists in Table A?

MERGE dbo.TA AS tgt
USING (
    SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
    FROM TB
    ) as src
ON (tgt.StuId  = src.StuId and tgt.ExamId   = src.ExamId )
WHEN MATCHED
    THEN UPDATE SET tgt.Status = 'remain'
WHEN NOT MATCHED
    THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
    VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name, Inserted.Listening, Inserted.Writing, Inserted.Reading, Inserted.TotalMarks, Inserted.Status;
GO 
  1. Compare marks of Listening, Writing, Reading, TotalMarks

如果您想同时获得这两个条件,那么您可以使用以下使用单个 MERGE 查询的完整解决方案

MERGE dbo.TA AS tgt
USING (
    SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
    FROM TB
    ) as src
ON (tgt.StuId  = src.StuId and tgt.ExamId   = src.ExamId )
WHEN MATCHED
    THEN UPDATE SET tgt.Status = 'remain', 
        tgt.Remarks = CASE
            WHEN src.Listening = tgt.Listening and src.Writing = tgt.Writing and src.Reading = tgt.Reading and src.TotalMarks = tgt.TotalMarks THEN 'none'
            ELSE  IIF(src.Listening  != tgt.Listening ,'Ori lis % = ' + CONVERT(NVARCHAR(100),src.Listening ) + '; New lis % = '  + CONVERT(NVARCHAR(100),tgt.Listening ) + ';','')
                + IIF(src.Writing    != tgt.Writing   ,'Ori wri % = ' + CONVERT(NVARCHAR(100),src.Writing   ) + '; New wri % = '  + CONVERT(NVARCHAR(100),tgt.Writing   ) + ';','')
                + IIF(src.Reading    != tgt.Reading   ,'Ori rea % = ' + CONVERT(NVARCHAR(100),src.Reading   ) + '; New rea % = '  + CONVERT(NVARCHAR(100),tgt.Reading   ) + ';','')
                + IIF(src.TotalMarks != tgt.TotalMarks,'Ori Ttl % = ' + CONVERT(NVARCHAR(100),src.TotalMarks) + '; New Ttl % = '  + CONVERT(NVARCHAR(100),tgt.TotalMarks) + ';','')
        END
WHEN NOT MATCHED
    THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
    VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name, 
    Inserted.Listening  as Listening_Ori  , src.Listening  as Listening_New  ,
    Inserted.Writing    as Writing_Ori    , src.Writing    as Writing_New    ,
    Inserted.Reading    as Inserted_Ori   , src.Reading    as Inserted_New   ,
    Inserted.TotalMarks as TotalMarks_Ori , src.TotalMarks as TotalMarks_New ,
    Inserted.Status, Inserted.Remarks;
GO 

SELECT * FROM TA
SELECT * FROM TB
GO