计算月度工作日的SQL查询在tbl_Calendar无数据时无结果,求助
解决月度工作日计算中Calendar表为空时返回空结果的问题
我来帮你排查并解决这个问题!你的查询在tbl_Calendar有数据时正常,但空表时返回空,核心原因是你用了隐式内连接(逗号分隔两张表)——当tbl_Calendar没有数据时,内连接的结果集直接为空,导致整个查询没有输出。另外你用的EXISTS判断也没法解决这个连接层面的问题,因为内连接已经把所有数据过滤掉了。
问题分析
原查询里的FROM tbl_Shift Shifts, tbl_Calendar CL是隐式内连接,相当于INNER JOIN:只有当两张表都有匹配数据时才会返回结果。一旦tbl_Calendar为空,这个连接就没有任何行,后续的计算自然也出不来结果。
解决方案
我们需要把tbl_Calendar的总假期数单独聚合计算,不管它有没有数据,都能得到一个有效的值(空表时为0),再和tbl_Shift的数据结合,避免用内连接过滤掉数据。这里提供两种可行的写法:
方法1:使用标量子查询获取总假期
declare @StartDate datetime = '2018-05-01'; declare @EndDate datetime = '2018-05-31'; SELECT (DATEDIFF(dd, @StartDate, @EndDate+1)) -(DATEDIFF(wk, @StartDate, @EndDate)) -ISNULL((CASE WHEN Shifts.IsAlternateOffday2 = 1 THEN (DATEDIFF(wk, @StartDate, @EndDate)) END), 0) -ISNULL((SELECT SUM(TotalHoldiays) FROM tbl_Calendar), 0) AS TotalWorkDays FROM tbl_Shift Shifts GROUP BY Shifts.IsAlternateOffday2
- 这里用
(SELECT SUM(TotalHoldiays) FROM tbl_Calendar)作为标量子查询,直接获取总假期数;当表为空时SUM返回NULL,用ISNULL转成0。 - 没有把
tbl_Calendar和tbl_Shift做连接,所以不管Calendar有没有数据,tbl_Shift的行都会被保留,确保查询能返回结果。
方法2:先聚合Calendar再LEFT JOIN
declare @StartDate datetime = '2018-05-01'; declare @EndDate datetime = '2018-05-31'; SELECT (DATEDIFF(dd, @StartDate, @EndDate+1)) -(DATEDIFF(wk, @StartDate, @EndDate)) -ISNULL((CASE WHEN Shifts.IsAlternateOffday2 = 1 THEN (DATEDIFF(wk, @StartDate, @EndDate)) END), 0) -ISNULL(Cal.TotalHolidays, 0) AS TotalWorkDays FROM tbl_Shift Shifts LEFT JOIN ( SELECT SUM(TotalHoldiays) AS TotalHolidays FROM tbl_Calendar ) Cal ON 1=1 -- 无条件关联,确保每个Shift行都能拿到假期数据 GROUP BY Shifts.IsAlternateOffday2, Cal.TotalHolidays
- 先对
tbl_Calendar做聚合,得到一行总假期数据(空表时为NULL)。 - 用
LEFT JOIN关联这个聚合结果,ON 1=1表示不需要匹配条件,确保tbl_Shift的所有行都能被保留,再用ISNULL把空假期数转成0。
额外提示
- 尽量避免使用隐式内连接(逗号分隔表),改用显式的
JOIN语句,可读性更强,也不容易出现这类过滤数据的问题。 - 原查询里的
CASE WHEN EXISTS(...) THEN SUM(...) END完全可以简化,因为SUM在无数据时会返回NULL,直接用ISNULL处理即可,不需要额外的EXISTS判断。
内容的提问来源于stack exchange,提问作者Doonie Darkoo
相关产品推荐
相关产品推荐

