基于Microsoft SSMS的检查表SQL查询:不良响应检测与耗时计算
问题分析与解决方案
错误原因
你当前的HasBadResponse逻辑存在问题:EXISTS子查询没有关联外层的ChecklistId,导致只要表中存在任意一条bad响应,所有ChecklistId的HasBadResponse都会返回1,无法针对每个检查表单独判断是否存在不良响应。
修正后的查询方案
方案1:修正原查询的关联逻辑
保留临时表的写法,但修复子查询的关联,并去掉冗余的DISTINCT:
DECLARE @StartEndStamps TABLE ( ChecklistId INT, FirstResponse DATETIME, LastResponse DATETIME ) INSERT INTO @StartEndStamps SELECT ChecklistId, MIN(ResponseDate), MAX(ResponseDate) FROM db.checklistResponses GROUP BY ChecklistId SELECT r.ChecklistId AS ChecklistNumber, CASE WHEN EXISTS (SELECT 1 FROM db.checklistResponses r_inner WHERE r_inner.ChecklistId = r.ChecklistId AND r_inner.Response = 'bad') THEN 1 ELSE 0 END AS HasBadResponse, DATEDIFF(SECOND, s.FirstResponse, s.LastResponse) AS Duration FROM db.checklistResponses r INNER JOIN @StartEndStamps s ON s.ChecklistId = r.ChecklistId GROUP BY r.ChecklistId, s.FirstResponse, s.LastResponse
方案2:更高效的单GROUP BY写法(推荐)
直接通过一次分组完成所有计算,避免临时表和JOIN操作,逻辑更简洁性能更优:
SELECT ChecklistId AS ChecklistNumber, MAX(CASE WHEN Response = 'bad' THEN 1 ELSE 0 END) AS HasBadResponse, DATEDIFF(SECOND, MIN(ResponseDate), MAX(ResponseDate)) AS Duration FROM db.checklistResponses GROUP BY ChecklistId
查询优化建议
- 优先使用单GROUP BY写法:一次扫描表完成所有聚合计算,减少数据库的IO和内存开销,比临时表+JOIN的方式效率更高
- 创建覆盖索引:为
db.checklistResponses创建包含ChecklistId、Response、ResponseDate的覆盖索引,让聚合查询直接从索引获取数据,无需回表:CREATE NONCLUSTERED INDEX IX_checklistResponses_ChecklistId ON db.checklistResponses (ChecklistId) INCLUDE (Response, ResponseDate); - 去掉冗余的DISTINCT:原查询中的
DISTINCT是多余的,GROUP BY本身会返回唯一的ChecklistId结果,无需额外去重
内容的提问来源于stack exchange,提问作者nawomack
相关产品推荐
相关产品推荐

