MS Access:提取唯一AssemblyID的电气连接器零件数据
解决方案
针对你的需求变更——筛选出所有属于电气连接器(PartClass = 1)的零件,且每个AssemblyID仅保留唯一一行,这里有两种清晰可靠的SQL实现方式:
方法一:窗口函数实现(推荐,逻辑清晰易维护)
用ROW_NUMBER()窗口函数可以轻松为每个AssemblyID分组后的行编号,我们只取每组里编号为1的行即可。如果需要保留每个AssemblyID中PartRefID最小的行(和你的示例结果完全匹配),可以这么写:
WITH ranked_parts AS ( SELECT p.PartRefID, p.PartDefID, p.AssemblyID, -- 按AssemblyID分组,每组内按PartRefID升序编号 ROW_NUMBER() OVER (PARTITION BY p.AssemblyID ORDER BY p.PartRefID) AS rn FROM Parts p INNER JOIN PartDefinitions pd ON p.PartDefID = pd.PartDefID WHERE pd.PartClass = 1 ) SELECT PartRefID, PartDefID, AssemblyID FROM ranked_parts WHERE rn = 1;
如果业务需求是保留每个AssemblyID中PartRefID最大的行,只需要把ORDER BY p.PartRefID改成ORDER BY p.PartRefID DESC就行。
方法二:关联子查询实现(延续你之前的思路)
如果你更习惯用子查询的写法,也可以通过找到每个AssemblyID对应的目标PartRefID来筛选:
SELECT p.* FROM Parts p INNER JOIN PartDefinitions pd ON p.PartDefID = pd.PartDefID WHERE pd.PartClass = 1 AND p.PartRefID = ( -- 找到当前AssemblyID下,PartClass=1的最小PartRefID SELECT MIN(p1.PartRefID) FROM Parts p1 INNER JOIN PartDefinitions pd1 ON p1.PartDefID = pd1.PartDefID WHERE pd1.PartClass = 1 AND p1.AssemblyID = p.AssemblyID );
这个写法和窗口函数的逻辑完全一致,只是表达方式不同。
结果验证
以上两种方法都会返回你期望的结果:
| PartRefID | PartDefID | AssemblyID |
|---|---|---|
| 1 | 2 | c63df10b-8250-4aa5-9889-9e8046331dbf |
| 11 | 1 | db51f4a8-3ffa-41f7-81c1-a9accbbb299a |
| 67 | 6 | 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab |
| 77 | 5 | 38fa8b7a-2945-4546-8eab-7865a1e515b2 |
如果你的业务场景允许任意保留每个AssemblyID的一行(不需要指定最小/最大PartRefID),部分数据库(比如PostgreSQL)支持DISTINCT ON语法,但建议还是指定排序规则,保证结果的一致性。
内容的提问来源于stack exchange,提问作者Perry 59
相关产品推荐
相关产品推荐

