SQL Server - 基于所有列/存储数据的历史值进行合并

时间:2016-08-01 18:47:40

标签: sql-server tsql merge

假设我的SQL Server(2012)数据库中有以下表:

MyTable的

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"

我有以下数据(比如大约20000条记录),我想与我当前的表合并:

新数据

Col1:      Col2:     Col3:     Col4:    VersionNum:
--------------------------------------------------
Val11      Val21     Val31     Val41    1
Val12      Val22     Val32     Val42    1
Val13      Val23     Val33     Val43    1
                 ...

因此,第一个值与第一行完全匹配,而第二个值至少有一个元素不同

我希望我的桌子看起来像是:

MyTable的

Col1:      Col2:     Col3:     Col4:
------------------------------------
Val11      Val21     Val31     Val41
Val12a     Val22     Val32     Val42

或者,把它写成文字:

  1. 如果所有数据元素都匹配,则不要添加新行
  2. 如果任何一个或多个数据元素不同,则添加一个包含更新版本号的新行。
  3. 我发现this question似乎处理了类似的问题,但仅针对主键区别。我想知道在给出如此大的数据集用于合并时,最好/最有效的方法是什么?或者,如果有更好的模式(存档表或类似的东西,请分享 - 这对我来说都是非常新的,我希望尽可能干净,高效地完成工作。)

2 个答案:

答案 0 :(得分:1)

一种很棒的方法是使用MERGE()。您可以在MERGE()中澄清如果匹配(更新,插入,删除)等应该怎么做,以确保您没有重复项,只更新或插入您想要的记录。

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

https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

一个很好的例子:

https://www.simple-talk.com/sql/learn-sql-server/the-merge-statement-in-sql-server-2008/

答案 1 :(得分:0)

我假设您希望所有新行的版本号为2(或者比现有的max versionNum多1),因为这是唯一有意义的方法。首先使用没有ALL关键字的UNION获取合并的记录集:

select a.*,
       f.versionNum
  from (query1) a,
       firstTable f
 where a.col1 = f.col1
   and a.col2 = f.col2
   and a.col3 = f.col3
   and a.col4 = f.col4

调用此" query1"。现在加入firstTable标记原始记录:

select b.col1,
       b.col2,
       b.col3,
       b.col4,
       2 as versionNum
  from (query2) b
 where b.versionNum is null

这是query2。任何没有versionNum的东西都是新的,应该有versionNum = 2.所以:

(select max(versionNum) from firstTable) + 1

是您要插入的记录。

如果你需要使versionNum大于表中的当前最大值,你可以这样做

show

而不是2作为versionNum。