当所有连接条件都与TSQL匹配时,如何按特定顺序将两个表连接在一起

当所有连接条件都与TSQL匹配时,如何按特定顺序将两个表连接在一起,sql,tsql,Sql,Tsql,我的问题是这样的。我需要创建一个包含以下信息的视图 订单号、订单行、装箱单编号、发票编号 有更多的信息,但以上4个是问题所在 现有系统没有从装箱单到发票的连接,但装箱单和发票都连接到订单行 假设我在装箱单上有这些信息 Order1 Line1 PackingSlip1 20 Order1 Line1 PackingSlip2 30 Order1 Line2 PackingSlip3 25 Order1 Line2 PackingSlip4 25 以及发票表中的此信息 Order1 Line1

我的问题是这样的。我需要创建一个包含以下信息的视图

订单号、订单行、装箱单编号、发票编号

有更多的信息,但以上4个是问题所在

现有系统没有从装箱单到发票的连接,但装箱单和发票都连接到订单行

假设我在装箱单上有这些信息

Order1 Line1 PackingSlip1 20
Order1 Line1 PackingSlip2 30
Order1 Line2 PackingSlip3 25
Order1 Line2 PackingSlip4 25
以及发票表中的此信息

Order1 Line1 Invoice1 20
Order1 Line1 Invoice2 30
Order1 Line2 Invoice3 25
Order1 Line2 Invoice4 25
这里基本上有两种情况。第一个很简单,因为我们可以在数量、订单号和订单行上将PackingSlip表连接到InvoiceTable。问题是,如果我们这样做,第二个场景(数量相同)将有4行作为输出,而不是只有2行

所以我的问题是。如何将这两个表连接在一起,以便匹配订单号和订单行。然后找到第一个匹配的数量并加入该行。所以我希望PackingSlip3与发票3匹配,PackingSlip4与发票4匹配

作为附加信息,装箱表有装箱日期,发票表有发票日期。所以我想加入最早的包装订单,行到最早的发票订单,行

任何帮助都将不胜感激。多谢各位

编辑。下面是一些示例代码

Declare @InvoiceTable as Table(
    OrderNumber nvarchar(10),
    OrderLine   int,
    InvoiceNumber nvarchar(10),
    QuantityInvoiced int
)

Declare @PackingTable as Table(
    OrderNumber nvarchar(10),
    OrderLine   int,
    PackingNumber nvarchar(10),
    QuantityPacked int
)

Insert into @PackingTable(OrderNumber, OrderLine, PackingNumber, QuantityPacked) Values ('O1', 1, 'P1', 20),('O1', 1, 'P2', 30), ('O1', 2, 'P3', 25), ('O1', 2, 'P4', 25)
Insert into @InvoiceTable(OrderNumber, OrderLine, InvoiceNumber, QuantityInvoiced) Values ('O1', 1, 'I1', 20),('O1', 1, 'I2', 30), ('O1', 2, 'I3', 25), ('O1', 2, 'I4', 25);

with ctePackingSlip as
(
    select distinct OrderNumber, OrderLine, PackingNumber, QuantityPacked
    from @PackingTable
), cteInvoice as
(
    select distinct OrderNumber, OrderLine, InvoiceNumber, QuantityInvoiced
    from @InvoiceTable
)
SELECT t0.OrderNumber, t0.OrderLine, PackingNumber, InvoiceNumber, t0.QuantityPacked
FROM ctePackingSlip As t0
JOIN @InvoiceTable As t1
    ON t0.OrderNumber = t1.OrderNumber 
   AND t0.OrderLine = t1.OrderLine
   AND t0.QuantityPacked = t1.QuantityInvoiced
问题是这会产生以下输出

O1 1 P1 I1 20

O1 1 P2 I2 30

O1 2 P3 I3 25

O1 2 P4 I3 25

O1 2 P3 I4 25

O1 2 P4 I4 25


正如您在末尾看到的,P3和P4有两行。我只想为每个

设置一行,这非常重要:

作为附加信息,装箱表有装箱日期,发票表有发票日期。所以我想加入最早的包装订单,行到最早的发票订单,行

根据包装/发票日期为每组中的行分配行号,然后将其添加到联接:

with ctePacking as
(
 SELECT OrderNumber, OrderLine, PackingSlipNumber, Quantity,
        ROW_NUMBER() OVER (PARTITION BY OrderNumber, OrderLine ORDER BY PackingDate ASC) RN
 FROM PackingSlip
)
, cteInvoice as
(
 SELECT OrderNumber, OrderLine, InvoiceNumber, Quantity,
        ROW_NUMBER() OVER (PARTITION BY OrderNumber, OrderLine ORDER BY InvoiceDate ASC) RN
 FROM Invoice
)

SELECT P.OrderNumber, P.OrderLine, P.PackingSlipNumber, I.InvoiceNumber
FROM ctePacking P
JOIN cteInvoice I ON P.OrderNumber = I.OrderNumber
              AND P.OrderLine = I.OrderLine
              AND P.RN = I.RN
编辑-一些解释:

这里的想法是,您知道条目的时间相互关联(第一个装箱单条目=第一个发票条目),但我假设这些时间可能略有不同,因此您不能直接加入它们

为了解决这个问题,我们可以按顺序时间对它们进行编号,然后加入该编号

ROW\u NUMBER()
是一个窗口函数,它将为我们可以加入的每一行(作为新列)分配一个数字。基本语法如下:

ROW_NUMBER()(按列划分按列分组顺序按列排序)

有关
行编号()
的更多信息,请参阅

在您的情况下,我们希望按日期时间订购,并按每个订单号和订单行分组。如果顺序总是一个接一个地完美插入,我们可能会完全删除分区分组,但这样做可能更安全,因此:

ROW_NUMBER()OVER(按医嘱编号划分,按医嘱日期划分医嘱行)RN--RN是新列的别名

现在,实现在主查询中添加行号列以供我们参考的最简单方法是使用CTE。这使我们可以创建列,将其命名为别名,并已将其用于最终查询。另一种选择是使用如下派生表:

SELECT P.OrderNumber, P.OrderLine, P.PackingSlipNumber, I.InvoiceNumber
FROM (SELECT OrderNumber, OrderLine, PackingSlipNumber, Quantity,
            ROW_NUMBER() OVER (PARTITION BY OrderNumber, OrderLine ORDER BY PackingDate ASC) RN
     FROM PackingSlip) P
JOIN (SELECT OrderNumber, OrderLine, InvoiceNumber, Quantity,
            ROW_NUMBER() OVER (PARTITION BY OrderNumber, OrderLine ORDER BY InvoiceDate ASC) RN
     FROM Invoice) I ON P.OrderNumber = I.OrderNumber
                    AND P.OrderLine = I.OrderLine
                    AND P.RN = I.RN
对于大多数人来说,CTE是一种更干净的方式来分离逻辑,并使最终查询更简单


总之,我们使用CTE将行号添加到基表数据中,然后我们查询CTE而不是基表,以访问和使用联接中的新RN列。

请使用实际示例数据,否则您可能会得到类似于替换(invoicenumber,'invoice,'Packingsslip')的建议=packingslipnumber哪一个可能不正确哪一列定义了“订单”?如果这只是“当我从表中选择*时它是如何来的”,那么这就是一个问题。创建一个适当的关系,不要希望基于查询的无序结果(它可能会突然改变,不应该依赖)。如果是“每行都有一个createddate,而且总是按照正确的顺序,因为订单总是按照发票上的顺序包装,而且只有一个人这样做,而且它是唯一的,尽管每个表中的顺序不同”,那么我们可以处理它(但它是脆弱的)..@CaiusJard请查看我的编辑,我在其中添加了一些示例代码。我不明白你关于哪列定义顺序的问题。问题是我们的ERP系统是如何建立的。因此,我们的业务需要一个视图,该视图包含将装箱单与发票联系起来的信息,但我们无法显示该视图,因为我们的ERP系统没有该视图。因此,我们正试图通过结合ERP系统所具有的功能来添加它。编辑我们面临的问题是,订单上的一行可能会被拆分为多个装运,并有多个发票或装箱单分配给它。我删除了我的答案,因为它不再相关。这正是我所需要的。它工作得很好。非常感谢你。你能解释一下步骤吗?我不太了解CTE的功能。具体地说,我不明白上面的行数。。。。部分我不知道这是在做什么。当然,我会编辑更多的解释来回答。谢谢!这个解释很好,我现在明白了。再次感谢你。