问题描述
如何使用 CROSS APPLY
(或 INNER JOIN
)根据其他表中的值从一个表中获取数据?
即我有以下表格:
表格说明:
产品ID | 说明 | TrackNum |
---|---|---|
361 | 测试 1 | 499 |
388 | 测试 2 | 003 |
004 | 5599 | |
238 | 测试 3 | 499 |
361 | 测试 10 | 555 |
004 | 测试 40 | 555 |
餐桌产品:
产品ID | 产品名称 | 价格 |
---|---|---|
361 | P1 | 5.00 |
388 | P2 | 5.00 |
004 | P3 | 12.00 |
238 | P4 | 6.00 |
515 | P5 | 7.00 |
636 | P6 | 7.00 |
775 | P7 | 7.00 |
858 | P8 | 8.00 |
表格发票:
产品ID | TrackNum | 发票ID |
---|---|---|
361 | 499 | 718 |
388 | 199 | 718 |
004 | 499 | 718 |
238 | 499 | 718 |
361 | 555 | 333 |
004 | 555 | 444 |
361 | 111 | 444 |
388 | 222 | 333 |
616 | 116 | 565 |
717 | 116 | 565 |
361 | 003 | 221 |
388 | 003 | 221 |
004 | 5599 | 728 |
我需要查询的是:
- 先进入 Invoices 表,只获取与指定的 InvoiceID 和 TrackNum 匹配的记录;
- 然后进入 Products 表并获取仅在我在步骤 1 中提取的数据和在 ProdID 上具有匹配的行数据存在于 Products 表中。
- 然后最终从 Descriptions 表中获取所有列,但仅限于我在第 2 步中获取且与 ProdID 匹配的行。
最后我需要的是这样的(如果我得到更多的列就好了,但我不想得到更多的行):
产品ID | 说明 | TrackNum |
---|---|---|
361 | 测试 1 | 499 |
004 | 5599 | |
238 | 测试 3 | 499 |
我有以下查询(我曾尝试使用 INNER JOIN
和 CROSS APPLY
) - 但它返回的行比我需要的多:
SELECT * FROM [Descriptions] AS [DES]
CROSS APPLY
(
select * from [Invoices] AS [INV] where [INV].[TrackNum] = '499' AND [INV].[InvoiceID] = '718'
) [INV]
CROSS APPLY
(
select * from [Products] AS [GP]
WHERE [GP].[ProdID] = [INV].[ProdID]
) [GP2]
WHERE
[DES].[ProdID] = [GP2].[ProdID]
order by [DES].[ProdID] asc
解决方法
根据您的描述,您需要以下内容,从您的 Invoices
表和 where 子句开始以获得正确的行,然后在 Products
和 Descriptions
上加入。
我猜您还想匹配 Description
上的 TrackNum
?因为看起来您对每个 Description
/ProdId
组合都有一个唯一的 TrackNum
。
select [INV].[ProdID],[DES].[Description],[INV].[TrackNum]
from [Invoices] as [INV]
inner join [Products] as [GP] on [GP].[ProdID] = [INV].[ProdID]
inner join [Descriptions] on [DES].[ProdID] = [GP].[ProdID] and [DES].[TrackNum] = [INV].[TrackNum]
where [INV].[TrackNum] = '499' AND [INV].[InvoiceID] = '718'
order by [DES].[ProdID] asc;
注意:您通常只将“CROSS APPLY”用于要运行/评估主表中每行内容的查询。
,SELECT
*
FROM
invoices AS i
LEFT JOIN
descriptions AS d
ON d.prodid = i.prodid
AND d.tracknum = i.tracknum -- you don't have this,but I think it's required.
LEFT JOIN
products AS p
ON p.prodid = i.prodid
WHERE
i.invoiceid = 718
AND i.tracknum = 499
ORDER BY
i.prodid
我担心的一件事是发票和说明都有一个名为 tracknum
的列,但您的查询和预期数据表明您不想希望将其包含在加入?这非常令人困惑,要么是一个糟糕的列名,要么是查询和示例结果中的错误。
在这种情况下,内连接就足够了。您不需要使用交叉应用