SQL 仅查询一次连接表行以将付款与发票相匹配

SQL Query to join tables rows only once to match payments to invoices

我有两个表,发票和付款,如下所示:

发票:

| 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

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

谢谢。

如果我没理解错的话,你可以用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.