【问题标题】:How to do Multiple Joins with Merge Into?如何使用 Merge Into 进行多个联接?
【发布时间】:2019-02-08 18:51:36
【问题描述】:

我有这 3 张桌子

  • 公司
    • 身份证
  • 分公司
    • 身份证
  • 项目
    • 身份证
    • 库存号

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

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

有些项目在公司只能出现一次,有些项目可以在每个分公司出现。

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

现在将通过 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。

编辑(来自 cmets):

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

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
)

【问题讨论】:

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


    【解决方案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
    

    【讨论】:

    • 抱歉什么含糊?所以我现在不使用类型表中的参数了吗?
    • 好的,我用一个例子更新了我的问题,希望它现在更有意义。
    • 好的,所以如果我理解正确,您还需要知道如何在 Target 中进行 JOIN。这有点复杂,因为您必须将其置于 MERGE 的 ON 条件下。我将编辑我的答案。
    • 好的,我正在尝试应用您的建议,如果现在有 2 个来源(一个用于表类型,一个用于此连接?如果是这样我如何指定两者) )?
    • 好吧,我得再玩一玩。你认为这样做会减慢代码速度吗?我正在使用此代码并发送一个包含 1000 条记录的数据表,我不确定它们是逐个处理还是批量处理。
    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    相关资源
    最近更新 更多