Как сделать несколько объединений с Merge Into? - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть эти 3 таблицы

  • Компания
    • id
  • Филиал
    • id
  • Предметы
    • id
    • StockNumber

Компания может иметь много филиалов, а филиал может иметь много элементов.

Теперь мне нужно написать запрос, который будет либо вставлять, либо обновлять элемент в зависимости от условий.

Некоторые элементы могут появляться в компании только один раз, а некоторые элементы могут появляться в каждой отрасли.

Проблема для меня - это те, которые могут появиться в компании только один раз.Я думаю, что мне нужно в основном объединить все эти таблицы вместе и выполнить проверку, но я не знаю, как сделать это объединение в "Merge Into Sp"

Я сделал тип таблицы, который выглядит какэто

CREATE TYPE ItemTableType AS TABLE   
( 
  BranchId INT,
  CompanyId INT
  Description nvarchar(Max),
  StockNumber: INT  
);  

В моем коде я могу передать companyId в свой тип таблицы

CREATE PROCEDURE dbo.Usp_upsert @Source ItemTableType readonly 
AS 
    MERGE INTO items AS Target 
    using @Source AS Source 
    ON 
     // need to somehow look at the companyId so I can then find the right record reguardlesss of which branch it sits in.
     Targert.CompanyId = source.CompanyId // can't do this just like this as Item doesn not have reference to company table.
     Target.StockNumber = source.StockNumber
    WHEN matched THEN 
      // update
    WHEN NOT matched BY target THEN 
      // insert

Редактировать

Образец данных

Company
Id Name
1   'A'
2  'B'

Branch
Id name CompanyId
1   'A.1'  1
2   'A.2'  1
3   'B.1'  2
4  'B.2'   3

Item
Id Name StockNumber BranchId
1  Wrench  12345      1
2  Wrench  12345      3
3  Hammer  484814     2
4  Hammer 85285825    4

ТеперьОбъемные данные будут отправляться в этот SP с помощью кода C # и выглядеть примерно так:

 DataTable myTable = ...;  

  // Define the INSERT-SELECT statement.  
  string sqlInsert = "dbo.usp_InsertTvp"  

  // Configure the command and parameter.  
  SqlCommand mergeCommand = new SqlCommand(sqlInsert, connection);  
  mergeCommand.CommandType = CommandType.StoredProcedure;
  SqlParameter tvpParam = mergeCommand.Parameters.AddWithValue("@Source", myTable);  
  tvpParam.SqlDbType = SqlDbType.Structured;  
  tvpParam.TypeName = "dbo.SourceTableType";  

  // Execute the command.  
  insertCommand.ExecuteNonQuery();  

Теперь скажите, когда приходит импорт записей, и данные выглядят так:

Wrench (Name),  12345 (StockNumber), 2 (BranchId..they are switching the branch of this item to another branch)

Если бы я просто отправил это, тогда, если бы я использовал BranchId + Stocknumber, ничего бы не обновлялось, и вставлялась бы новая запись, что было бы неправильно, так как теперь 2 ветви имеют одинаковый элемент (на основе stockNumber)

Я бы просто использовал StockNumber, тогда эти 2 записи будут обновлены.

1  Wrench  12345      1
2  Wrench  12345      3

Что неверно, так как эти записи принадлежат 2 различным компаниям.Таким образом, мне нужно также использовать companyId, поэтому мне нужно также проверить ID компании.

РЕДАКТИРОВАТЬ (из комментариев):

Я думаю, что я должен сделать что-то Target Dot.Это то, что я придумал до сих пор:

MERGE INTO Items AS Target 
using @Source AS Source 
ON Source.CompanyID=(
  SELECT TOP 1 Companies.Id 
  FROM Branches 
  INNER JOIN Companies 
    ON Branches.CompanyId = Companies.Id 
  INNER JOIN InventoryItems 
    ON Branches.Id = Target.BranchId 
  where Companies.Id = Source.CompanyId 
  and StockNumber = Source.StockNumber
)

1 Ответ

0 голосов
/ 08 февраля 2019

Описание того, что вам нужно сделать, слишком расплывчато для меня, чтобы быть конкретным, но вы можете просто сделать запрос с JOINs в качестве источника.Мне нравится помещать его в CTE, чтобы он выглядел примерно так:

WITH cte AS (SELECT query with JOINS)
MERGE INTO items AS Target 
using cte AS Source 
ON 

РЕДАКТИРОВАТЬ: Чтобы также выполнить JOIN для цели (items), вам нужно сделать это в условиях ON:

WITH cte AS (SELECT query with JOINS)
MERGE INTO items AS Target 
using cte AS Source 
ON Source.CompanyID=(
  SELECT TOP 1 CompanyId 
  FROM TableWithCompanyId 
  JOIN Target 
    ON JoinCondition=true
 )...

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

EDIT 2, основанная на последней попытке:

Попробуйте это так:

MERGE INTO Items AS Target 
using @Source AS Source 
ON Source.CompanyID=(
  SELECT TOP 1 Companies.Id 
  FROM Branches 
  INNER JOIN Companies 
    ON Branches.CompanyId = Companies.Id 
  WHERE Branches.Id = Target.BranchId 
)
and Target.StockNumber = Source.StockNumber
...