如何合并合并成多个联接?

时间:2019-02-08 18:51:37

标签: sql-server join stored-procedures sql-server-2017

我有这3张桌子

  • 公司
    • id
  • 分行
    • id
  • 物品
    • id
    • 库存编号

公司可以有很多分支,而一个分支可以有很多项目。

现在,我必须编写一个查询,该查询将根据条件插入或更新项目。

某些项目只能在公司中出现一次,而某些项目可以在每个分支机构中出现。

对我来说,问题是只能在公司中出现一次的问题。我想我基本上需要将所有这些表连接在一起并进行检查,但是我不知道如何在“合并到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

现在,大量数据将通过C#代码发送到此SP中,并且看起来像这样

 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,因此还需要检查companyId。

编辑(根据评论):

我认为我必须做一些目标点。到目前为止,这是我想出的:

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 :(得分:1)

对于我来说,您需要做什么的描述太模糊了,因此您可以简单地使用JOIN作为源进行查询。我喜欢将其放在CTE中,使其看起来像这样:

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

编辑:要同时在目标(items)上执行JOIN操作,您需要在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
 )...

我知道您的表涉及从物品到公司的两个表格,但是上面的示例向您展示了我认为您所缺少的技术。

编辑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