【发布时间】:2022-11-23 02:24:45
【问题描述】:
在 SQL Server 2016 (v13) 中连接两个表时,我遇到以下问题,恳请您的帮助。
我有 2 个表,Revenues 和 Cashins。
Revenues:
| RevenueID | ProductID | InvoiceNo | Amount |
|---|---|---|---|
| 123 | 456 | 987 | 1000 |
| 234 | 456 | 987 | 1000 |
Cashins:
| CashinID | ProductID | InoviceNo | Amount |
|---|---|---|---|
| ABC | 456 | 987 | 1000 |
| CDE | 456 | 987 | 1000 |
目标是自动将现金与收入匹配(但只有一次!)。
两个表都有其唯一 ID,但用于连接这些表的列是
- 产品编号
- 发票号
- 数量
对于具有这些条件的每个表中只有一行的条目,一切正常。
但有时,这些列中有几行具有相同的值(如上)但具有唯一 ID(这不是错误,但应该是这样)。
它的问题是,加入它会产生笛卡尔积。
要重新创建表,请使用以下语句:
DROP TABLE IF EXISTS Revenues
GO
CREATE TABLE Revenues
(
RevenueID [nvarchar](10) NULL,
ProductID [nvarchar](10) NULL,
InvoiceNo [nvarchar](10) NULL,
Amount money NULL
)
GO
DROP TABLE IF EXISTS CashIns
GO
CREATE TABLE CashIns
(
CashinID [nvarchar](10) NULL,
ProductID [nvarchar](10) NULL,
InvoiceNo [nvarchar](10) NULL,
Amount money NULL
)
GO
INSERT INTO [Revenues] VALUES ('123', '456', '987', 1000)
INSERT INTO [Revenues] VALUES ('234', '456', '987', 1000)
INSERT INTO [CashIns] VALUES ('ABC', '456', '987', 1000)
INSERT INTO [CashIns] VALUES ('BCD', '456', '987', 1000)
期望的输出:
| RevenueID | ProductID | InvoiceNo | Amount | CashinID |
|---|---|---|---|---|
| 123 | 456 | 987 | 1000 | ABC |
| 234 | 456 | 987 | 1000 | CDE |
SELECT
R.RevenueID,
R.ProductID,
R.InvoiceNo,
R.Amount,
C.CashinID,
FROM
[Revenues] R
LEFT JOIN
[CashIns] C ON R.ProductID = C.ProductID
AND R.InvoiceNo = C.InvoiceNo
AND R.Amount = C.Amount
结果:
| RevenueID | ProductID | InvoiceNo | Amount | CashinID |
|---|---|---|---|---|
| 123 | 456 | 987 | 1000 | ABC |
| 123 | 456 | 987 | 1000 | CDE |
| 234 | 456 | 987 | 1000 | ABC |
| 234 | 456 | 987 | 1000 | CDE |
这在理论上是有道理的,但我似乎无法找到每行只使用一次的解决方案。
我发现并尝试过的两件事是窗口函数和带有TOP(1)选择的OUTER APPLY函数。两者都得出相同的结果:
SELECT
*
FROM
[Revenues] R
OUTER APPLY
(SELECT TOP(1) *
FROM [CashIns] C) C
它从 Revenues 表中返回所需的列,但仅匹配 Cashins 表中的第一个外观:
| RevenueID | ProductID | InvoiceNo | Amount | CashinID |
|---|---|---|---|---|
| 123 | 456 | 987 | 1000 | ABC |
| 234 | 456 | 987 | 1000 | ABC |
我还考虑过更新 Revenues 表,以便匹配的 CashinID 位于一行的旁边,然后每次检查 CashinID 是否尚未在该表中使用,但我做不到工作...
非常感谢您在正确方向上提供的任何帮助或提示!
【问题讨论】:
-
您的数据关系存在根本问题。您通过非唯一标识符加入。我看到的唯一可能的解决方案是对 Revenues 中的行进行排序,对 Cashins 中的行进行排序,然后匹配 row_number。
标签: sql-server join unique window-functions cartesian-product