如何基于另一张表的日期范围查询匹配记录 SQL 实操问题
问题排查
你的SQL存在以下3个核心逻辑错误:
- JOIN方向完全颠倒:你的需求是筛选TableA中符合条件的客户,应该以存储TableA衍生数据的
#Temp表作为左表,左关联TableB,而非反过来从TableB左连临时表。 - WHERE条件逻辑错误:你现在的筛选条件是「TableB的日期不在区间内」,这只会筛出区间外的TableB记录,完全匹配不到「区间内无TableB记录」的需求;正确逻辑是左关联后筛选
TableB.ClientID IS NULL,代表区间内没有匹配的TableB记录。 - 临时表存在性判断语法错误:SQL Server中判断临时表存在需要用
OBJECT_ID函数,你写的If #temp NOT NULL语法不合法,执行会报错。
可选优化点
- 用
DATEADD(MONTH, -6, CAST(a.Date AS date))替代DATEADD(DAY, -180, xxx),更符合「前6个月」的业务描述,避免大小月/闰年导致的天数误差。 - 可以直接用CTE替代临时表,简化代码。
修正后的查询代码
-- 正确的临时表存在性判断 IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp CREATE TABLE #Temp (ClientID int, Start_dt date, end_dt date) Insert into #Temp select ClientID, -- 若严格要求6个月就保留这行,要180天就换回DATEADD(DAY,-180,CAST(a.Date AS date)) DATEADD(MONTH, -6, CAST(a.Date AS date)), DATEADD(DAY, 45, CAST(a.Date AS date)) FROM TableA a -- 1、查询符合条件的客户清单 SELECT DISTINCT x.ClientID, CAST(a.Date AS date) AS ServiceDate FROM #Temp x LEFT JOIN Table_B b ON b.ClientID = x.ClientID -- 区间匹配条件写在ON中,仅过滤右表TableB的匹配记录 AND CAST(b.Date AS date) BETWEEN x.Start_dt AND x.end_dt -- 为空代表区间内无TableB对应记录,符合需求 WHERE b.ClientID IS NULL -- 2、统计符合条件的客户总数 SELECT COUNT(DISTINCT x.ClientID) AS QualifiedClientCount FROM #Temp x LEFT JOIN Table_B b ON b.ClientID = x.ClientID AND CAST(b.Date AS date) BETWEEN x.Start_dt AND x.end_dt WHERE b.ClientID IS NULL
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

