T-SQL WHERE与IN子句问题:如何返回全部TagName统计结果
嘿,我来帮你搞定这个问题!
首先,你遇到的问题可能是因为原查询里的IN子句虽然能正确返回所有目标TagName,但如果某个TagName在你指定的时间范围内没有对应的记录,SUM(Value)就不会生成该行数据——而你硬编码的时候,那些TagName刚好都有数据,所以能看到全部结果。不过没关系,我们有几种替代方法可以解决这个问题,而且不用硬编码:
方法1:用INNER JOIN替代IN子句
这种方法和你原查询逻辑类似,但用连接的方式来关联目标TagName,通常更高效,也能确保返回所有符合条件且有数据的TagName:
SELECT h1.TagName, SUM(h1.Value) AS Monthly FROM History h1 INNER JOIN ( -- 先拿到所有目标TagName SELECT DISTINCT TagName FROM History WHERE TagName LIKE '%DailykWh' ) h2 ON h1.TagName = h2.TagName WHERE h1.DateTime BETWEEN '2020-11-01 00:00:00' AND '2020-11-08 23:59:59' GROUP BY h1.TagName ORDER BY h1.TagName
方法2:用LEFT JOIN返回所有目标TagName(包括无数据的站点)
如果有些站点在指定时间范围内没有数据,你也想让它们显示出来(值为0),可以用左连接,从目标TagName集合出发关联历史数据:
SELECT h2.TagName, ISNULL(SUM(h1.Value), 0) AS Monthly FROM ( SELECT DISTINCT TagName FROM History WHERE TagName LIKE '%DailykWh' ) h2 LEFT JOIN History h1 ON h2.TagName = h1.TagName AND h1.DateTime BETWEEN '2020-11-01 00:00:00' AND '2020-11-08 23:59:59' GROUP BY h2.TagName ORDER BY h2.TagName
这里用ISNULL把SUM的空值转换成0,确保无数据的站点也有明确的数值显示。
方法3:直接利用你的Tag表(更推荐)
既然你已经有Tag表存储所有TagName信息,完全可以直接从Tag表过滤目标TagName,这样比从History表查DISTINCT更高效:
SELECT t.TagName, ISNULL(SUM(h.Value), 0) AS Monthly FROM Tag t LEFT JOIN History h ON t.TagName = h.TagName AND h.DateTime BETWEEN '2020-11-01 00:00:00' AND '2020-11-08 23:59:59' WHERE t.TagName LIKE '%DailykWh' GROUP BY t.TagName ORDER BY t.TagName
方法4:用EXISTS子句替代IN
EXISTS子句的逻辑是“检查是否存在符合条件的记录”,性能通常比IN更好,尤其是当History表数据量很大的时候:
SELECT TagName, SUM(Value) AS Monthly FROM History h1 WHERE EXISTS ( SELECT 1 FROM History h2 WHERE h2.TagName = h1.TagName AND h2.TagName LIKE '%DailykWh' ) AND DateTime BETWEEN '2020-11-01 00:00:00' AND '2020-11-08 23:59:59' GROUP BY TagName ORDER BY TagName
你可以根据自己的需求选择合适的方法,优先推荐用Tag表的方案,因为它更贴合你的表结构,效率也更高!
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

