使用拆分比较在两个表之间合并数据

时间:2015-11-30 17:11:23

标签: sql-server tsql

我有两个表,我需要比较数据并更新一个表记录。请让我知道如何做到这一点。这是方案

Proj1表  这是第一个需要同步数据的表

ID Text            reqId
1   R1|R2           12            
2   R2|R3           12
3   R3|R5|R2        12

Proj2表  这是正在进行数据更新的表

    ID Text Active reqId
    3   R1    1     12
    4   R3    1     12
    5   R4    1     12

我需要从Proj1中获取每条记录,然后使用拆分函数对于拆分中的每个文本,比较这两个表之间的文本字段结果应该类似于下面。我们正在将Proj2中的数据同步到类似于Proj1。

    ID Text Active  reqId
    3   R1    1       12    (Ignore as it exists in both tables)
    4   R3    1       12    (Ignore as it exists in both tables)
    5   R4    0       12    (Update to inactive as it does not exist Proj1 table but exists in )
    6   R2    1       12    (Insert as it does not exist in Proj2 table, insert only once)
    7   R5    1       12    (Insert as it does not exist in Proj2 table, insert only once)

2 个答案:

答案 0 :(得分:0)

如果您使用的是SQL Server 2008或更高版本,则可以使用MERGE语句,如下所示:

/*
CREATE TABLE Proj1 (
    ID INT PRIMARY KEY,
    Text VARCHAR(100) NOT NULL,
    reqId INT NOT NULL
)

INSERT INTO Proj1 VALUES (1,'R1|R2',12)
INSERT INTO Proj1 VALUES (2,'R2|R3',12)
INSERT INTO Proj1 VALUES (3,'R3|R5|R2',12)

CREATE TABLE Proj2 (
    ID INT IDENTITY PRIMARY KEY,
    Text VARCHAR(100) NOT NULL,
    Active BIT NOT NULL,
    reqId INT NOT NULL
)

SET IDENTITY_INSERT Proj2 ON
INSERT INTO Proj2 (ID, Text, Active, reqId) VALUES (3,'R1',1,12)
INSERT INTO Proj2 (ID, Text, Active, reqId) VALUES (4,'R3',1,12)
INSERT INTO Proj2 (ID, Text, Active, reqId) VALUES (5,'R4',1,12)
SET IDENTITY_INSERT Proj2 OFF
*/
GO
CREATE FUNCTION dbo.Split(@String VARCHAR(1000),@Separator CHAR(1))
RETURNS @Result TABLE (
    Position INT IDENTITY PRIMARY KEY,
    Value VARCHAR(1000)
) AS
BEGIN
    DECLARE @Pos INT, @Prev INT
    SET @Prev=0
    WHILE 1=1 BEGIN
        SET @Pos=CHARINDEX(@Separator,@String,@Prev+1)
        IF @Pos=0 BREAK
        INSERT INTO @Result (Value) VALUES (SUBSTRING(@String,@Prev+1,@Pos-@Prev-1))
        SET @Prev=@Pos
    END
    INSERT INTO @Result (Value) VALUES (SUBSTRING(@String,@Prev+1,LEN(@String)))
    RETURN
END
GO

MERGE INTO dbo.Proj2 p2
USING (
    SELECT DISTINCT reqId, Value FROM dbo.Proj1 p1
    CROSS APPLY dbo.Split(Text,'|') s
) x
ON p2.Text=x.Value AND p2.reqId=x.reqId
WHEN NOT MATCHED THEN INSERT VALUES (Value,1,reqid)
WHEN NOT MATCHED BY SOURCE THEN UPDATE SET Active=0
WHEN MATCHED AND Active=0 THEN UPDATE SET Active=1;

SELECT * FROM dbo.Proj2

稍后编辑:我在MERGE语句中添加了第三个WHEN子句,以处理行已存在但没有Active标志的情况(尽管此案例未出现在示例中)数据)。

答案 1 :(得分:0)

您也可以在没有MERGE语句的情况下处理此问题,如下所示:

INSERT INTO Proj2
SELECT Value,1,reqid
FROM (
    SELECT DISTINCT reqId, Value FROM dbo.Proj1 p1
    CROSS APPLY dbo.Split(Text,'|') s
) x
WHERE NOT EXISTS (
    SELECT *
    FROM Proj2 p2
    WHERE p2.Text=x.Value AND p2.reqId=x.reqId
)   

UPDATE Proj2 SET Active=0
FROM Proj2 p2
WHERE NOT EXISTS (
    SELECT *
    FROM (
        SELECT DISTINCT reqId, Value FROM dbo.Proj1 p1
        CROSS APPLY dbo.Split(Text,'|') s
    ) x
    WHERE p2.Text=x.Value AND p2.reqId=x.reqId
)   

UPDATE Proj2 SET Active=1
FROM Proj2 p2
INNER JOIN (
    SELECT DISTINCT reqId, Value FROM dbo.Proj1 p1
    CROSS APPLY dbo.Split(Text,'|') s
) x ON p2.Text=x.Value AND p2.reqId=x.reqId
WHERE p2.Active=0

(我使用了另一个答案中提到的Split函数)