Как вставить и обновить с определенными условиями? - PullRequest
0 голосов
/ 25 апреля 2019

Я хочу обновить и вставить записи в таблицу фактов.Есть некоторые условия.

1) Мне нужно обновить строку записи при изменении записи в тот же день

2) и вставить, когда запись изменяется на другую дату (Date_Import).

Но на данный момент я думаю, что проблема в левом соединении.Когда я запускаю код, он обновляет все записи, а не только хорошие.

Таблица: факты

Fact_Key    Date_Import Date_of_Work WorkshopID  WorkforceNeeded
----------- ----------- ------------ ----------- ---------------
1           20190425    20190501     2           220
2           20190425    20190501     3           40
3           20190425    20190504     2           6
4           20190425    20190504     3           35

Таблица: подготовка

Date_Import Date_of_Work WorkshopId  WorkforceNeeded
----------- ------------ ----------- ---------------
20190425    20190501     2           185
20190426    20190501     3           68
20190425    20190504     2           6
20190425    20190504     3           35

Ожидаемый результат

Fact_Key    Date_Import Date_of_Work WorkshopID  WorkforceNeeded
----------- ----------- ------------ ----------- ---------------
1           20190425    20190501     2           185          -- updated
2           20190425    20190501     3           40
3           20190425    20190504     2           6
4           20190425    20190504     3           35
5           20190426    20190501     3           68           -- inserted

РЕДАКТИРОВАНИЕ:

ФактРезультат, если я выполню код с этими двумя таблицами:

Fact_Key    Date_Import Date_of_Work WorkshopID  WorkforceNeeded
----------- ----------- ------------ ----------- ---------------
1           20190425    20190501     2           185
2           20190425    20190501     2           185
3           20190425    20190501     2           185
4           20190425    20190501     2           185
5           20190425    20190501     3           40
6           20190425    20190504     2           6
7           20190425    20190504     3           35

Код, который не работает полностью

----------------------------------------------------------------------
-- UPDATE (first because we update only record already in the table)
----------------------------------------------------------------------
begin
    update DWH.Fact
    set
        -- Colonne Business 
        [Date_Import] = GETDATE(),
        [WorshopId] = S.WorkshopId,
        [Date_of_Work] =  convert(int, convert(char(8), Convert(Date,S.Date_of_Work), 112)),
        [WorkforceNeeded] =  Convert(int,S.WorkforceNeeded)
    FROM Staging S
        left outer join
        (
        SELECT *
        FROM    (
            SELECT *
            ,RANK() OVER  (PARTITION BY F.[WorkshopId], F.[Date_of_Work] ORDER BY F.[Date_Import] DESC) AS Ranking  
            FROM DWH.Fact F    
            ) Inter
        WHERE Ranking = 1
        )BA         
        on BA.WorkshopId = S.WorkshopId and BA.Date_of_Work = S.Date_of_Work 

    where BA.Fact_KEY is not null
        and BA.WorkforceNeeded != convert(int,S.WorkforceNeeded)
        and BA.Date_Import = GETDATE()
end

----------------------------------------------------------------------
-- INSERT
----------------------------------------------------------------------
begin

    insert into DWH.Fact(
        [WorkshopId]
        ,[Date_Import]
        ,[Date_of_Work]
        ,[WorkforceNeeded])
    Select 
            ISNULL(A.WorkshopId,-1) as WorkshopId,
            GETDATE() Date_Import,
            S.Date_of_Work as [Date_of_Work],
            Convert(int,S.WorkforceNeeded) as WorkforceNeeded
    from Staging S 
        left outer join
        (
        SELECT *
        FROM    (
            SELECT *
            ,RANK() OVER  (PARTITION BY F.[WorkshopId], F.[Date_of_Work] ORDER BY F.[Date_Import] DESC) AS Ranking  
            FROM DWH.Fact F    
            ) Inter
        WHERE Ranking = 1
        )BA         
        on BA.WorkshopId = S.WorkshopId and BA.Date_of_Work = S.Date_of_Work

    where 
        (
        BA.Fact_KEY is null
        ) 
        OR 
        (
        BA.Fact_KEY is not null
        and BA.Date_Import != GETDATE()
        and BA.WorkforceNeeded != convert(int,S.WorkforceNeeded)
        )

end

Отредактированный пример.

Ответы [ 2 ]

1 голос
/ 25 апреля 2019

Я бы использовал MERGE.Я попытался с приведенным выше примером данных, и это сработало для меня:

MERGE Fact as target
USING Staging as source
ON (source.WorkshopId = target.WorkshopId AND source.Date_Import = target.Date_Import)
--If WorkshopId and Date_Import and Date_of_Work has a match, then update
WHEN MATCHED AND source.Date_of_Work = target.Date_of_Work THEN
    UPDATE SET target.WorkforceNeeded = source.WorkforceNeeded
--If not, insert instead
WHEN NOT MATCHED THEN
    INSERT (Date_Import, Date_of_Work, WorkshopId, WorkforceNeeded) VALUES (Date_Import, Date_of_Work, WorkshopId, WorkforceNeeded);

Что он делает, он проверяет, есть ли совпадения WorkshopId, Date_Import и Date_of_Work, и обновляет WorkforceNeeded.Если совпадения нет, вместо этого делается вставка.
Обязательно запустите это в тестовой среде или в begin/rollback transaction просто для уверенности.Allso MERGE не поддерживается до SQL Server 2008 и более поздних версий.

Вот еще немного информации об операторе MERGE: https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-2017

0 голосов
/ 26 апреля 2019

Я нашел способ, который кажется хорошим, используя Merge. Кто-нибудь видит другой, более эффективный способ сделать это?

        ----------------------------------------------------------------------
        -- UPDATE 
        ----------------------------------------------------------------------
        begin
            MERGE DWH.Fact AS TARGET
            USING Staging AS SOURCE 

            -- champs à match 
            ON (TARGET.Date_of_Work = SOURCE.Date_of_Work) 
                AND (TARGET.WorkshopId = SOURCE.WorkshopId) 

            --When records are matched, update the records if there is any change
            WHEN MATCHED  AND TARGET.Date_Import = SOURCE.Date_Import AND TARGET.WorkforceNeeded <> SOURCE.WorkforceNeeded THEN 
            UPDATE SET 
                TARGET.WorkforceNeeded = SOURCE.WorkforceNeeded
            ;
        ----------------------------------------------------------------------
        -- INSERT 
        ----------------------------------------------------------------------
            MERGE DWH.Fact AS TARGET
            USING Staging AS SOURCE 
            -- champs à match 
            ON (TARGET.Date_of_Work = SOURCE.Date_of_Work) AND (TARGET.WorkshopId = SOURCE.WorkshopId) AND (TARGET.WorkforceNeeded = SOURCE.WorkforceNeeded)  

            --When no records are matched, insert the incoming records from source table to target table
            WHEN NOT MATCHED BY TARGET THEN 
            INSERT (Date_of_Work, WorkshopId, Date_Import, WorkforceNeeded)
            VALUES (SOURCE.Date_of_Work ,SOURCE.WorkshopId ,SOURCE.Date_Import ,SOURCE.WorkforceNeeded)
        ;

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