如何修改MS-SQL查询,返回含无AD1测试记录的空值行?
解决思路与修正后的查询
你的问题核心出在原查询的WHERE rf2.testType = 'AD1'条件上——这个条件会在JOIN操作完成后,直接过滤掉所有没有匹配到AD1测试的记录。哪怕你用了FULL OUTER JOIN也没用,因为WHERE子句会把那些rf2字段为NULL的行彻底排除,导致没有AD1测试的单元信息无法返回。
下面提供两种可行的修正方案,都能保证即使没有AD1测试时,也会返回含空值的行,满足你关联到大报表的需求:
方案一:先获取最新AD1测试,再左关联到基础数据
这种方式逻辑更清晰,先单独筛选出每个LinkID对应的最新AD1测试记录,再关联到单元、测试信息和关联表的全量数据上:
WITH LatestAD1Tests AS ( SELECT LinkID, testdate, Testname, -- 按LinkID分区,取每个分组内最新的AD1测试 ROW_NUMBER() OVER(PARTITION BY LinkID ORDER BY testdate DESC) AS rn FROM dbo.Tests WHERE Testname = 'AD1' -- 注意:你的Tests表字段是Testname,原查询里的testType是笔误,必须修正 ) SELECT rs.record_ID, rs.SN, rs.Data1, rf.Info1, rf.Data1 AS TestingData_Data1, rf1.LinkID, lat.testdate, lat.Testname FROM dbo.Unit rs -- 保留所有单元和测试信息的匹配/不匹配记录 FULL OUTER JOIN dbo.TestingData rf ON rs.SN = rf.SN -- 用COALESCE处理SN可能为空的情况,确保和Link表正确关联 FULL OUTER JOIN dbo.Link rf1 ON COALESCE(rs.SN, rf.SN) = rf1.SN -- 左关联最新AD1测试,没有匹配的测试时返回NULL LEFT JOIN LatestAD1Tests lat ON rf1.LinkID = lat.LinkID AND lat.rn = 1 ORDER BY COALESCE(rs.SN, rf.SN) ASC;
方案二:直接修改原查询的条件位置与筛选逻辑
如果你更倾向于基于原查询调整,可以把AD1的筛选条件从WHERE移到JOIN的ON子句中,同时修正窗口函数的分区字段:
SELECT * FROM ( SELECT -- 基于Link表的LinkID分区,避免因没有测试记录导致分区字段为NULL ROW_NUMBER() OVER(PARTITION BY rf1.linkID ORDER BY ISNULL(rf2.testDate, '1900-01-01') DESC) AS rn, rs.*, rf.*, rf1.*, rf2.testdate, rf2.Testname FROM dbo.Unit rs FULL OUTER JOIN dbo.TestingData rf ON rs.SN = rf.SN FULL OUTER JOIN dbo.Link rf1 ON COALESCE(rs.SN, rf.SN) = rf1.SN -- 把AD1的筛选条件放到ON子句中,只关联符合条件的测试记录 LEFT JOIN dbo.Tests rf2 ON rf1.linkID = rf2.linkID AND rf2.Testname = 'AD1' ) T -- 保留最新的AD1测试(rn=1),以及没有AD1测试的记录(测试字段为NULL但rn=1) WHERE rn = 1 ORDER BY COALESCE(T.SN, T.SN) ASC;
关键注意事项
- 笔误修正:你的
Tests表字段是Testname,原查询中写的testType是错误的,必须修正才能正确筛选AD1测试。 - 避免WHERE过滤空行:把测试类型的筛选条件放在JOIN的ON子句中,而不是WHERE子句,这样不会过滤掉没有匹配测试的基础记录。
- 分区字段选择:窗口函数的分区要基于
Link表的LinkID,而不是Tests表的字段,避免因为没有测试记录导致分区字段为NULL,打乱分组逻辑。
内容的提问来源于stack exchange,提问作者Just_Stacking
相关产品推荐
相关产品推荐

