【问题标题】:SQL Query to join tables rows only once to match payments to invoicesSQL 查询仅连接表行一次以匹配付款到发票
【发布时间】:2020-01-08 22:43:08
【问题描述】:

我有两张表,发票和付款是这样的:

发票:

| Vendor | Invoice No | Amount |
|--------|------------|--------|
| V1     | A1         |   1200 |
| V1     | A2         |   1000 |
| V1     | A3         |   1500 |
| V1     | A4         |   2100 |
| V1     | A5         |   1500 |
| V2     | A1         |    100 |
| V2     | A2         |   1100 |
| V2     | A3         |    400 |
| V2     | A4         |    200 |
| V2     | A5         |    600 |

付款:

| Vendor | Payment No | Amount |
|--------|------------|--------|
| V1     | P1         |   1000 |
| V1     | P2         |   1000 |
| V1     | P3         |   1500 |
| V1     | P4         |   2000 |
| V2     | P1         |    300 |
| V2     | P2         |    400 |
| V2     | P3         |    400 |

我想加入这些表,以便对于每个发票行,我只想匹配一个付款行。 例如,V1、P1 和 P2 的金额均为 1000,但只有第一个 (P1) 与发票 A2 匹配。 对于每个供应商,不匹配的仍应显示在下面,如下所示:

| Seq | Vendor | Invoice No | Invoice Amount | Vendor | Payment No | Payment Amount |
|-----|--------|------------|---------------:|--------|------------|---------------:|
| 1   | V1     | A1         |           1200 |        |            |                |
| 2   | V1     | A2         |           1000 | V1     | P1         |           1000 |
| 3   | V1     | A3         |           1500 | V1     | P3         |           1500 |
| 4   | V1     | A4         |           2100 |        |            |                |
| 5   | V1     | A5         |           1500 |        |            |                |
| 6   |        |            |                | V1     | P2         |           1000 |
| 7   |        |            |                | V1     | P4         |           2000 |
| 8   | V2     | A1         |            100 |        |            |                |
| 9   | V2     | A2         |           1100 |        |            |                |
| 10  | V2     | A3         |            400 | V2     | P2         |            400 |
| 11  | V2     | A4         |            200 |        |            |                |
| 12  | V2     | A5         |            600 |        |            |                |
| 13  |        |            |                | V2     | P1         |            300 |
| 14  |        |            |                | V2     | P3         |            400 |

显然,简单的连接不起作用,因为 V1、P1 和 P2 都将匹配 V1 A2

和 V1 A2 将出现两次,如以下 SQLFiddle 示例所示: SQLFIDDLE

如何在不使用游标的情况下实现上述目标?

谢谢。

【问题讨论】:

    标签: sql sql-server sql-server-2016


    【解决方案1】:

    如果我理解正确,你可以使用row_number()full join

    select i.*, p.*
    from (select i.*, row_number() over (partition by vendor, amount order by ?) as sequm
          from invoices i
         ) i full join
         (select p.*, row_number() over (partition by vendor, amount order by ?) as sequm
          from payments p
         ) p
         on p.vendor = i.vendor and p.amount = i.amount and p.seqnum = i.seqnum;
    

    请注意,这是排列付款和发票的一种非常基本的方式。在现实世界中,金额通常不会排列得那么好——部分付款、预付款等等。

    如果这最终成为您真正的问题,请提出一个问题,并提供适当的样本数据和所需的结果。

    Here 是一个 SQL Fiddle。

    【讨论】:

    • 使用 seqnum 进行匹配并不总是有效,正如 SQLFiddle 所见。 P1 根本不匹配。关于您对付款和发票在现实世界中排列不整齐的担忧,我同意。在我的真实案例中,我实际上将发票与来自两个不同系统的发票对齐,但我使用了发票和付款,因此更容易提出问题。
    • @unubar 。 . .如果您使用问题中的代码,它会起作用。我为那个版本添加了 SQL Fiddle。
    • 感谢您添加 SQL Fiddle。匹配正在根据需要进行。我现在更好地理解了逻辑。我最初的问题中唯一剩下的就是要有一个如图所示的序列号,以便每个供应商的不匹配行出现在同一个供应商之后。现在,所有不匹配的行都单独出现了。
    • 我进行了修改,以使每个供应商的不匹配行现在出现在同一供应商之后 SQLFiddle。可以做得更好吗?
    • @unubar 。 . .你的表情很好。我没有意识到序列号是问题的一部分,否则我会包含一个类似的结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2019-03-07
    • 1970-01-01
    • 2013-12-30
    • 2014-04-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多