SQL插入一组项目的最新版本

时间:2010-04-30 19:18:46

标签: sql sql-server sql-server-2005

我正在尝试确定一种处理下面方案的好方法。我有以下两个数据库表,以及示例数据。表1包含按项目分组的分布。项目可以有一个或多个发行版。分发可以有一个或多个帐户。帐户分配了一个百分比。可以通过添加或删除帐户以及更改百分比来修改分发。

表2跟踪分布,为每个分布分配版本号。 我需要能够将新的分布从Table1复制到Table2,但只能在两个条件下:

1. the entire distribution does not already exist 
2. the distribution has been modified (accounts added/removed or percentages changed).

注意:的 将分发从Table1复制到Table2时,我需要比较分发中的所有帐户和百分比,以确定它是否已存在。插入新分发时,我需要增加VersionID(max(VersionID)+ 1)。

因此,在提供的示例中,已修改分发(12345,1),添加帐号7,以及更改分配的百分比。应将整个分发复制到第二个表,在此过程中将VersionID增加到3。

有问题的数据库是SQL Server 2005。

Table1
------
ProjectID   AccountDistributionID   AccountID   Percent
12345       1                       1           25.0
12345       1                       2           25.0
12345       1                       7           50.0
56789       2                       3           25.0
56789       2                       4           25.0
56789       2                       5           25.0
56789       2                       6           25.0

Table2
------
ID  VersionID   Project ID  AccountDistributionID   AccountID   Percent
1    1           12345       1                       1           50.0
2    1           12345       1                       2           50.0
3    2           56789       2                       3           25.0
4    2           56789       2                       4           25.0
5    2           56789       2                       5           25.0
6    2           56789       2                       6           25.0

2 个答案:

答案 0 :(得分:0)

假设您知道从Table1中提取哪个分发版,您可以动态确定应该使用的版本,如下所示:

Insert Table2( VersionId, ProjectId, AccountDistributionId, AccountId, Percent )
Select Coalesce(
                (
                Select Max(VersionId)
                From Table1 As T1
                Where T1.Id = T.Id
                ), 0) + 1 As VersionId
    , ProjectId, AccountDistributionId, AccountId, Percent
From Table1 As T
Where ProjectId = 12345
    And AccountDistributionId = 1

关于确定更难的“任何新分布”,它取决于“新”的定义方式。

<强> ADDITION

您询问了如何确定该设置已更改。一种解决方案是在保存时使用帐户分布存储值的哈希值。如下所示:

Update AccountDistributions
Set AccountHash = HashBytes('SHA1'
                            , (
                              Select '|' + Cast(AccountId As varchar(10)) + '|' + Cast(Percent As varchar(30))
                              From Table1 As T1
                              Where T1.AccountDistributionID = AccountDistributions.Id
                              Order By T1.AccountId, T1.Percent
                              For Xml Path('')
                              ))

然后,您可以使用它来确定该组的任何成员是否已更改。另一种解决方案是每当对集合发生更改时将DateTime值更新到父表中,并将相同的值写入Table2。然后,您可以将最后一个DateTime与父表中的DateTime进行比较,以确定是否有任何更改。

答案 1 :(得分:0)

经过多次试验,我决定采用不同的方法。以下查询是所做内容的概要。


declare @accountDistributionVersionID int

select @accountDistributionVersionID = isnull(max(VersionID), 0)
from Table2 

insert into Table2
select @accountDistributionVersionID + rank,
       ProjectID, AccountDistributionID, AccountID, Percent 
from 
(
    select  D.*,
            dense_rank() over (order by ProjectID, AccountDistributionID) as rank
    from   
    (
        select distinct t2.* from
        (
            select t.ProjectID, t.AccountDistributionID, t.AccountID, t.Percent 
            from Table1 as t
            where not exists(select * from Table2 as t2
                           where t2.ProjectID = t.ProjectID
                           and t2.AccountDistributionID = t.AccountDistributionID
                           and t2.AccountID = t.AccountID
                           and t2.Percent = t.Percent
                           and VersionId = (select max(VersionID) 
                                            from compass.Table2 t3
                                            where t2.ProjectID = t3.AccountDistributionID
                                            and t2.AccountDistributionID = t3.AccountDistributionID) )
        ) as t
        cross apply
        (
            select t3.ProjectID, t3.AccountDistributionID, t3.AccountID, t3.Percent
            from Table1 As t3
            where t.ProjectID = t3.ProjectID
            and t.AccountDistributionID = t3.AccountDistributionID
        ) as t2 
    ) as D
) as T

  • 我从目标表中获取最大版本ID。
  • 我只检索已从源表更改的帐户分发,使用DENSE_RANK函数生成伪版本号。
  • 最后,我插入到目标表中,其VersionID为(先前检索到的最大VersionID)+ rank

似乎运作良好。反馈将不胜感激。