sql - 如何进行高级 SQL 连接谓词/提示以避免不需要的行?
问题描述
第一部分是对我正在处理的真实世界情况的描述,我正在构建一份关于库存互换的报告,其中我将与资产相关的报告表、包含资产详细信息的表和 RMA 请求表分开,但与哪个资产被其他资产替换,只是与报告订单相关联的 RMA 订单的模糊关系。
我有四张桌子。
- 表 1 代表了故障设备的报告。
- 表 2 是一个清单表,其中包含设备详细信息等。
- 表 3 代表替换订单。
- 表 4 表示订单-替换关系。
所以记录是这样的。
table 1 are something like.
orderNo - reported item
1 1
1 2
2 56
2 34
2 23
3 15
table 2
device id lots of device detailed stuff in columns.
1 ...
2 ...
3 ...
...
15
23
34
56
table 3 (replacements)
rmaid replacement
1 3
1 4
2 7
2 8
2 9
3 16
这是我试图解决的问题的一个例子,也是我的问题出现的地方。
create table report(
ID int not null,
itemID int );
insert into report (ID, ItemID)
values (1,1),(1,2),(2,56),(2,34),(2,23),(3,15)
create table device(
ID int not null,
dev_detail nvarchar(50)
);
insert into device (ID, dev_detail)
values (1,'det1'),(2,'det2'),(3,'det3'),(4,'det4'),(5,'det5'),
(6,'det6'),(7,'det7'),(8,'det8'),(9,'det9'),(15,'det15'),
(16,'det16'),(23,'dev23'),(34,'det34'),(56,'det56')
create table replacement(
id int not null,
ItemID int );
insert into replacement (ID, ItemID)
values (1,3),(1,4),(2,7),(2,8),(2,9),(3,16)
create table [report-replacement](
ID int not null,
reportID int,
replaceID int);
insert into [report-replacement] (ID, reportID, replaceID)
values (1,1,1),(2,2,2),(3,3,3)
select
rep.ID as report_id,
rep.itemID as reported_item,
rep.dev_detail as reported_item_detail,
rep.replaceID as report_replace_id,
rma.id as rma_id,
rma.ItemID as rma_item,
rma.dev_detail as rma_item_detail
from
(
select report.ID,report.itemID,device.dev_detail, replaceID
from
report
inner join device on report.itemID = device.ID
inner join [report-replacement] on reportID = [report-replacement].reportID
) as Rep
inner join
(
select
replacement.id,replacement.ItemID,device.dev_detail
from
replacement
inner join device on replacement.ItemID = device.ID
) as RMA
on Rep.replaceID = RMA.id
drop table report, device,replacement,[report-replacement]
这是所需的输出,我想帮助为主内部连接构建一个谓词连接,以便我得到报告项目与替换项目的 1 比 1 比率:
report id, item id, item details, rma_id, rma_item, rma_item_detail
1 1 det1 1 3 det3
1 2 det2 1 4 det4
2 56 det56 2 7 det7
2 34 det34 2 8 det8
2 23 det23 2 9 det9
3 15 det15 3 16 det16
这是执行示例代码的结果,问题是我得到了很多行,我只使用内部连接。不应该有那么多,我的问题是是否有特殊的连接谓词,一些聪明的方法来获得所需的输出。
report_id reported_item reported_item_detail report_replace_id rma_id rma_item rma_item_detail
1 1 det1 1 1 3 det3
1 2 det2 1 1 3 det3
2 56 det56 1 1 3 det3
2 34 det34 1 1 3 det3
2 23 dev23 1 1 3 det3
3 15 det15 1 1 3 det3
1 1 det1 1 1 4 det4
1 2 det2 1 1 4 det4
2 56 det56 1 1 4 det4
2 34 det34 1 1 4 det4
2 23 dev23 1 1 4 det4
3 15 det15 1 1 4 det4
1 1 det1 2 2 7 det7
1 2 det2 2 2 7 det7
2 56 det56 2 2 7 det7
2 34 det34 2 2 7 det7
2 23 dev23 2 2 7 det7
3 15 det15 2 2 7 det7
1 1 det1 2 2 8 det8
1 2 det2 2 2 8 det8
2 56 det56 2 2 8 det8
2 34 det34 2 2 8 det8
2 23 dev23 2 2 8 det8
3 15 det15 2 2 8 det8
1 1 det1 2 2 9 det9
1 2 det2 2 2 9 det9
2 56 det56 2 2 9 det9
2 34 det34 2 2 9 det9
2 23 dev23 2 2 9 det9
3 15 det15 2 2 9 det9
1 1 det1 3 3 16 det16
1 2 det2 3 3 16 det16
2 56 det56 3 3 16 det16
2 34 det34 3 3 16 det16
2 23 dev23 3 3 16 det16
3 15 det15 3 3 16 det16
它将订单的每条记录与替换的每条记录相乘,并且它应该只对先前与设备连接的两个表进行内部连接以获取详细信息,因此您可以看到每个设备号都获取其设备详细信息(16 获取16)。
我发现在加入设备详细信息表时,连接 RMA 和 Reps 都可以,但是表报告与表 [report-replacement] 的内部连接无法正常工作,因此我将 on 子句顺序从 reportID = [report-替换].reportID 到 [report-replacement].reportID = reportID,这会将行数从 36 行减少到 14 行。
解决方案
这是我的问题的解决方案。
select
rep.ID as report_id,
rep.itemID as reported_item,
rep.dev_detail as reported_item_detail,
rep.replaceID as report_replace_id,
rma.id as rma_id,
rma.ItemID as rma_item,
rma.dev_detail as rma_item_detail,
Rep.seq,
rma.seq
from
(
select report.ID,report.itemID,device.dev_detail, [report-replacement].replaceID,
ROW_NUMBER() OVER (PARTITION BY report.id ORDER BY report.id) AS seq
from
report
inner join device on device.ID = Report.ID
inner join [report-replacement] on [report-replacement].reportID = Report.ID
) as Rep
inner join
(
select
replacement.id,replacement.ItemID,device.dev_detail,
ROW_NUMBER() OVER (PARTITION BY replacement.id ORDER BY replacement.id) AS seq
from
replacement
inner join device on device.ID = replacement.ItemID
) as RMA
on rep.replaceID = RMA.id AND rep.seq=rma.seq
该问题通常称为代理交叉连接。
解决方案似乎是基于使用 ROW_NUMBER() OVER (PARTITION BY replacement.id ORDER BY replacement.id) AS seq
推荐阅读
- perl - 使用 SAFEGUARD 为 HP Nonstop Guardian 编写 SSH 脚本
- php - 如何在 laravel 中使用 with 方法将令牌传递给视图
- python - 仅在基类中运行 __init__
- c# - C# 控制台在输入后关闭但保持代码运行
- batch-file - 批处理文件中的 Javascript 重新定位 IE 窗口
- r - 大型 R 数据框 - 如何有效地计算列
- python - 对象比较失败
- .htaccess - htaccess 不会重定向到第二个顶级文件夹
- python - 数据帧的索引与作为参数传递的列表不同
- php - 递归地将目录中的所有子目录和文件添加到数组中