SQL для вставки последней версии группы элементов - PullRequest
0 голосов
/ 30 апреля 2010

Я пытаюсь найти хороший способ справиться со сценарием ниже. У меня есть следующие две таблицы базы данных, а также примеры данных. Таблица 1 содержит распределения, сгруппированные по проектам. Проект может иметь одно или несколько распределений. Распределение может иметь одну или несколько учетных записей. Аккаунту присвоен процент. Распределения могут быть изменены путем добавления или удаления учетной записи, а также изменения процентов.

Таблица2 отслеживает дистрибутивы, присваивая номер версии каждому дистрибутиву. Мне нужно иметь возможность копировать новые дистрибутивы из Таблицы1 в Таблицу2, но только при двух условиях:

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

Примечание: При копировании дистрибутива из Таблицы 1 в Таблицу 2 мне нужно сравнить все учетные записи и проценты в распределении, чтобы определить, существует ли он уже. При вставке нового дистрибутива мне нужно увеличить 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 голосов
/ 11 мая 2010

После долгих экспериментов я решил пойти другим путем. Следующий запрос представляет собой краткий обзор того, что было сделано.


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

  • Я получаю максимальный VersionID из таблицы назначения.
  • Я получаю только распределения учетных записей, которые изменились из исходной таблицы, генерируя номер версии псевдо с помощью функции DENSE_RANK.
  • Наконец, я вставляю в таблицу назначения, с VersionID (ранее извлеченный макс. VersionID) + rank

Кажется, все работает хорошо. Обратная связь будет принята с благодарностью.

0 голосов
/ 30 апреля 2010

Предполагая, что вы знаете, какой дистрибутив извлечь из Таблицы1, вы можете динамически определить версию, которую следует использовать, например:

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

Что касается определения "любого нового дистрибутива", который является более жестким и зависит от того, как определяется "новый".

Сложение

Вы спрашивали о том, как определить, что набор изменился. Одним из решений является сохранение хеша значений в распределении Аккаунта при его сохранении. Так что-то вроде:

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 в родительской таблице, чтобы определить, изменилось ли что-либо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...