我希望通过将一个表(tableA)与另一个表(tableB)进行比较,在一个表(tableA)中找到新的,已修改的和已删除的记录。两个表都具有相同的模式,并具有唯一的ID字段。
在我的情况下,tableA最初与tableB相同,但它已由一些外部组织编辑,一旦完成编辑,他们通过ZIP文件将表发回,我们重新填充(截断并插入)那个数据到tableA。所以我想找出tableA中哪些记录发生了变化。我正在使用SQL Server 2012。
我可以使用"来获取新的和修改过的记录,除了"关键字:
select * from tableA
except
select * form tableB
(让我们调用上述结果A)
我也可以删除和修改记录:
select * from tableB
except
select * form tableA
(让我们调用上述结果B)
问题是,ResultsA和ResultsB都有相同的修改/编辑记录。因此修改/编辑的记录加倍。我可以在ResultsA和ResultsB上使用内部联接或交叉来获取仅修改的记录(将此结果称为结果C)。但是,我需要在ResultsA和ResultsC之间再次使用join / except来获取新的记录,并在ResultsB和ResultsC之间再次加入/除了只删除记录......我尝试this和this,但他们不适合我。
显然这不好。有没有更优雅,更简单的方法来查找已经删除,修改或添加到tableA中的记录与tableB相比?
答案 0 :(得分:5)
怎么样:
-- DELETED
SELECT B.*, 'DELETED' AS 'CHANGE_TYPE'
FROM TableB B
LEFT JOIN TableA A ON B.PK_ID = A.PK_ID
WHERE A.PK_ID IS NULL
UNION
-- NEW
SELECT A.*, 'NEW' AS 'CHANGE_TYPE'
FROM TableA A
LEFT JOIN TableB B ON B.PK_ID = A.PK_ID
WHERE B.PK_ID IS NULL
UNION
-- MODIFIED
SELECT B.*, 'MODIFIED' AS 'CHANGE_TYPE'
FROM (
SELECT * FROM TableA
EXCEPT
SELECT * FROM TableB
) S1
INNER JOIN TableB B ON S1.PK_ID = B.PK_ID;
不完全优雅,但有效。
答案 1 :(得分:1)
根据我的理解,我提出了以下解决方案。
DECLARE @tableA TABLE (ID INT, Number INT)
DECLARE @tableB TABLE (ID INT, Number INT)
INSERT INTO @tableA VALUES
(1,10),
(2,20),
(3,30),
(4,40)
INSERT INTO @tableB VALUES
(1,11),
(2,20),
(4,40),
(5,50)
SELECT *,'Modified or deleted' as 'Status' FROM
(
select * from @tableA
except
select * from @tableB
)a WHERE ID NOT IN
(
select ID from @tableB
except
select ID from @tableA
)
UNION
SELECT *,'New' as 'Status' FROM
(
select * from @tableB
except
select * from @tableA
)b WHERE ID NOT IN
(
SELECT ID FROM
(
select * from @tableA
except
select * from @tableB
)a WHERE ID NOT IN
(
select ID from @tableB
except
select ID from @tableA
)
)
答案 2 :(得分:0)
您可以使用OUTPUT子句:
从受INSERT,UPDATE或DELETE语句影响的每一行返回信息或基于表达式的表达式。这些结果可以返回到处理应用程序,以用于确认消息,存档和其他此类应用程序要求。或者,可以将结果插入表或表变量中。
请参阅以下内容,抱歉,我没有适合您的实用代码。但请注意,SQL输出子句可用于在执行插入或更新时从“inserted”和“deleted”(新值和旧值)表中返回任何值。 follow this for more info
答案 3 :(得分:0)
另一种非常有效的解决方案是使用两个表之间不存在交叉的地方。它非常紧凑。
SELECT
IsNull(tableB.ID,tableA.ID) as 'ID',
IsNull(tableB.Number,tableA.Number) as 'Number',
'Action' = CASE
WHEN tableB.ID IS NULL THEN 'Deleted'
WHEN tableA.ID IS NULL THEN 'Created'
ELSE 'Updated'
END
FROM tableA
FULL OUTER JOIN tableB
ON tableB.ID = tableA.ID
WHERE
NOT EXISTS (SELECT tableB.* INTERSECT SELECT tableA.*)
这使表扫描保持最小,并提供对新记录,已删除记录和已更改记录的检测。
我把这三个人放在小提琴里,令人惊讶的是他们的编纂方式有多么不同。
答案 4 :(得分:0)
ages = [20,20,11,12,10,11,15]
age_counts={} #define dict
for i in ages:
#if age_counts does not have i, set its count to 1
#increment otherwise
if not age_counts.has_key(i):
age_counts[i]=1
else:
age_counts[i]+=1
#you can now have counts stored
for i in age_counts:
print i, age_counts[i]
答案 5 :(得分:0)
这个没有主键也有点优雅。(在我看来!)
WITh A AS (SELECT 1,2,3 FROM DUAL
UNION ALL
SELECT 1,3,2 FROM DUAL
UNION ALL
SELECT 1,3,1 FROM DUAL),
B AS (SELECT 1,3,2 FROM DUAL
UNION ALL
SELECT 1,2,3 FROM DUAL
UNION ALL
SELECT 1,3,5 FROM DUAL
)
,
C AS
(SELECT * FROM A
MINUS
SELECT * FROM B
),
D AS( SELECT * FROM b
MINUS
SELECT * FROM A)
SELECT C.* ,'Deleted' FROM c
UNION ALL
SELECT D.* ,'Added' FROM D