Проблема обновления SQL Merge - PullRequest
0 голосов
/ 11 апреля 2019

Я пытаюсь увеличить код проекта при выполнении операции слияния SQL

У меня есть две таблицы. Один имеет много информации, в том числе клиентов и проектов. Я хочу объединить имя клиента и имя проекта из одной таблицы в другую. Эта статья прекрасна и показала мне, как делать то, что мне нужно было сделать

https://www.mssqltips.com/sqlservertip/1704/using-merge-in-sql-server-to-insert-update-and-delete-at-the-same-time/

Однако мне нужно сохранить номер проекта, который увеличивается каждый раз, когда запись добавляется и остается один, когда вы редактируете имя клиента или проекта. Если проект удален, мы продолжаем со следующего доступного номера. Я пытался сделать это, используя номер строки над разделом, но это не дало мне правильное количество проектов.

Используя пример статей и для визуализации, мне понадобится еще один столбец под названием «Тип с едой» или «Напиток» в качестве ответа, и вы получите

Item     Cost Code   Type
Tea      10    1     Drink
Coffee   12    2     Drink
Muffin   11    1     Food
Biscuit  4     2     Food

1 Ответ

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

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

--Create a target table
Declare @Products TABLE 
(
   ProductID INT PRIMARY KEY,
   ProductName VARCHAR(100),
   ProductNumber int,
   ProductType VARCHAR(100),
   Rate MONEY
) 

--Insert records into target table
INSERT INTO @Products
VALUES
   (1, 'Tea',       1,'Drink',10.00),
   (2, 'Coffee',    2,'Drink', 20.00),
   (3, 'BiscuitX1', 1,'Food', 45.00) ,
   (4, 'Muffin',    2,'Food', 30.00),
   (5, 'BiscuitX2', 3,'Food', 40.00),
   (6, 'BiscuitX3', 4,'Food', 45.00),
   (7, 'Donut',     5, 'Food', 30.00),
   (8, 'BiscuitX4', 6,'Food', 40.00),
   (9, 'BiscuitX5', 7,'Food', 45.00)  
--Create source table
Declare @UpdatedProducts TABLE 
(
   ProductID INT PRIMARY KEY,
   ProductName VARCHAR(100),
   ProductNumber int,
   ProductType VARCHAR(100),
   Rate MONEY
) 

--Insert records into source table
INSERT INTO @UpdatedProducts
VALUES
   (1, 'Tea',           0,'Drink', 10.00),
   (2, 'Coffee',        0,'Drink', 25.00),
   (4, 'Muffin',        0,'Food', 35.00),
   (7, 'Donut',         0, 'Food', 30.00),
   (10, 'Pizza',        0,'Food', 60.00),
   (11, 'PizzaLarge',   0,'Food', 80.00)

Вы видите, что я добавил ProductNumber и ProductType. для таблицы @UpdatedProducts Я предполагаю, что у вас нет номера продукта, если вы его сделаете, то сделаете прямое слияние без проблем, если у вас его нет, вам нужно его найти.

, поэтому давайте сначала обновим ProductNumber в @ updatedProducts

;with cte as (
    select u.ProductID,u.ProductName,u.ProductType,u.Rate 
    ,coalesce(p.ProductNumber,row_number() over (partition by u.ProductType order by u.ProductID)
    +(select max(pp.ProductNumber) from @Products pp where pp.ProductType=u.ProductType)
    -(select Count(*) from @UpdatedProducts uu 
        inner join @Products ppp on ppp.ProductID=uu.ProductID
        where uu.ProductType=u.ProductType)) [ProductNumber]
    from @UpdatedProducts u
    left outer join @Products p on p.ProductID=u.ProductID
)
update a
    set a.[ProductNumber]=cte.[ProductNumber]
    From @UpdatedProducts a
        inner join cte on cte.ProductID=a.ProductID

Я не нашел способа поместить это в слияние напрямую.

Результат @UpdatedProducts после обновления будет таким, как показано ниже: -

ProductID   ProductName ProductNumber   ProductType Rate
=========   =========== =============   =========== ====
1           Tea         1               Drink       10.00
2           Coffee      2               Drink       25.00
4           Muffin      2               Food        35.00
7           Donut       5               Food        30.00
10          Pizza       8               Food        60.00
11          PizzaLarge  9               Food        80.00

Так что теперь мы можем сделать прямое слияние, как показано ниже: -

--Synchronize the target table with refreshed data from source table
MERGE @Products AS TARGET
USING @UpdatedProducts AS SOURCE 
ON (TARGET.ProductID = SOURCE.ProductID) 
--When records are matched, update the records if there is any change
WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName OR TARGET.Rate <> SOURCE.Rate 
    THEN UPDATE SET TARGET.ProductName = SOURCE.ProductName, TARGET.Rate = SOURCE.Rate ,TARGET.ProductNumber= TARGET.ProductNumber --left alone on edit
--When no records are matched, insert the incoming records from source table to target table
WHEN NOT MATCHED BY TARGET 
THEN INSERT (ProductID, ProductName, Rate,ProductNumber,ProductType) 
    VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate,SOURCE.ProductNumber,SOURCE.ProductType)-- increments every time a record is added 
--When there is a row that exists in target and same record does not exist in source then delete this record target
WHEN NOT MATCHED BY SOURCE 
THEN DELETE 
--$action specifies a column of type nvarchar(10) in the OUTPUT clause that returns 
--one of three values for each row: 'INSERT', 'UPDATE', or 'DELETE' according to the action that was performed on that row
OUTPUT $action, 
DELETED.ProductID AS TargetProductID, 
DELETED.ProductName AS TargetProductName, 
DELETED.Rate AS TargetRate, 
INSERTED.ProductID AS SourceProductID, 
INSERTED.ProductName AS SourceProductName, 
INSERTED.Rate AS SourceRate; 


SELECT * FROM @Products

Результат @Products будет таким, как показано ниже: -

ProductID   ProductName ProductNumber   ProductType Rate
=========   =========== =============   =========== ====
1           Tea         1                Drink       10.00
2           Coffee      2                Drink       25.00
4           Muffin      2                Food        35.00
7           Donut       5                Food        30.00
10          Pizza       8                Food        60.00
11          PizzaLarge  9                Food        80.00

Для номеров продуктов (1,3,4,6,7) все были пропущены, а новый пищевой продукт Pizza взял Продукт № 8 и продолжал оставаться Продуктом 9 для PrizzaLarge. надеюсь, это поможет.

...