SQL存储过程:筛选指定日期同时保留Left Join的NULL行
搞定Left Join后丢失无匹配行的问题
这问题我太熟了——你踩了Left Join里筛选条件位置的经典坑!核心原因是你把关联表的日期筛选条件放在了WHERE子句里,直接把Left Join变成了Inner Join的效果,导致没有对应投喂数据的储罐行被过滤掉了。
直接上修改后的存储过程
ALTER PROCEDURE [dbo].[sp_GetFeedDate10_TEST] @daycurrent DATE AS BEGIN SELECT TANK.Name, TANK.Tank_Pond_uID, FEED.FeedValue, FEED.Date FROM aa_Tanks_Ponds TANK LEFT JOIN aa_Feed_Chart FEED ON TANK.Tank_Pond_uID = FEED.Tank_Pond_uID -- 关键:把日期筛选移到JOIN的ON子句里,而不是WHERE AND FEED.Date = DATEADD(DAY, -10, @daycurrent) WHERE TANK.Site_Name = 'Dry Creek' ORDER BY TANK.Tank_Pond_uID END
为啥这么改就对了?
- 用Left Join时,
ON子句管的是两个表怎么关联、要关联哪些行——它只会过滤关联表(aa_Feed_Chart)里不符合日期条件的记录,但绝不会丢掉主表(aa_Tanks_Ponds)的任何一行。哪怕某个储罐没有对应日期的投喂记录,它依然会出现在结果里,投喂相关的字段显示为NULL。 - 要是把日期条件放到
WHERE里,SQL会先做完Left Join(得到所有储罐行,包括无投喂的),然后再用WHERE过滤掉所有FEED.Date不符合条件的行——这就把那些FEED.Date为NULL的行也一并删了,最后就只剩有匹配投喂记录的储罐,完全违背了你Left Join的初衷。
测试效果
执行sp_GetFeedDate10_TEST '05/30/2018',就能得到你想要的结果:
Name Tank_Pond_uID FeedValue Date ----------------------------------------------- B01 DCB01 90 2018-05-20 B02 DCB02 90 2018-05-20 B03 DCB03 NULL NULL B04 DCB04 NULL NULL B05 DCB05 NULL NULL
内容的提问来源于stack exchange,提问作者C. Ayers
相关产品推荐
相关产品推荐

