存储过程查询需求:按日期去重返回单设备每日数据
解决方案:实现每日一行的设备数据查询
问题根源
你当前使用的DISTINCT无法实现每日一行的原因是:它会对SELECT子句中的所有列(DEVICE, VALUE, DATE, DATE1)做去重判断。只要同一天内存在不同的VALUE或带时间部分的DATE1,就会被判定为不同行,导致重复结果。
修正方案
根据需求,我们需要按日期维度分组,从每天的多条记录中筛选出单条有效数据(或做聚合计算),这里提供两种常用实现方式:
方式1:取每天的最新/最早记录
使用ROW_NUMBER()窗口函数,按设备+日期分组,对每天的记录按时间排序后取第一行:
WITH DailyData AS ( SELECT DEVICE, VALUE, DATE, DATE1, -- 按设备+日期分组,按时间倒序(取最新)或正序(取最早)排序 ROW_NUMBER() OVER (PARTITION BY DEVICE, CAST(DATE1 AS DATE) ORDER BY DATE1 DESC) AS RowNum FROM tableName WHERE DEVICE = @DeviceId -- 修正时间范围条件:确保记录时间在传入的起止区间内 AND DATE1 >= @StartDate AND DATE1 <= @EndDate AND ABS(VALUE) >= 0 ) SELECT DEVICE, VALUE, DATE, DATE1 FROM DailyData WHERE RowNum = 1 ORDER BY DATE1 ASC
如果需要取当天最早的记录,只需把ORDER BY DATE1 DESC改为ORDER BY DATE1 ASC。
方式2:对每日数据做聚合计算
如果不需要单条记录,而是需要当天数据的统计值(如平均值、最大值、总和),可以用GROUP BY实现:
SELECT DEVICE, -- 根据业务需求选择聚合函数,比如平均值、最大值 AVG(VALUE) AS DailyAvgValue, -- 取日期部分 CAST(DATE1 AS DATE) AS RecordDate, -- 可选:取当天的第一个/最后一个时间戳 MIN(DATE1) AS FirstRecordTime, MAX(DATE1) AS LastRecordTime FROM tableName WHERE DEVICE = @DeviceId AND DATE1 >= @StartDate AND DATE1 <= @EndDate AND ABS(VALUE) >= 0 GROUP BY DEVICE, CAST(DATE1 AS DATE) ORDER BY RecordDate ASC
适配小时级查询
以上两种方案都天然支持小时级范围查询:
- 当传入
2023-12-25 10:00:00至2023-12-25 13:00:00时,CAST(DATE1 AS DATE)会统一为2023-12-25,最终返回该日期下符合时间范围的单条记录(或聚合值)。 - 如果查询跨天的小时范围(如
2023-12-25 22:00:00至2023-12-26 02:00:00),会分别返回两天的对应数据。
修正后的存储过程调用示例
EXEC [dbo].[exampleProcedure] 'ABC','2023-12-25 12:00:00','2024-01-04 15:00:00'
内容的提问来源于stack exchange,提问作者Kadir Çolak
相关产品推荐
相关产品推荐

