【问题标题】:Return value of a column based on the date column taking the value closest to xx:00 and xx:30基于日期列的列的返回值,取最接近 xx:00 和 xx:30 的值
【发布时间】:2020-09-24 03:27:16
【问题描述】:

我试图以 30 分钟的间隔返回数据,但如果 30 分钟没有数据,我想取最接近 30 分钟或 0 分钟标记的值,公差为 -5 +5,如果仍然没有数据在 +5 -5 的范围内,即 55-05 或 25-35 将不会返回任何值。 目前我有一个 sql 语句,可以每隔 30 分钟返回 55-05 和 25-35 的平均值,但我现在只想要一个最接近 30 分钟的值,我可以使用 55-00 或 25-30如果 55-05 和 25-35 做不到。我现在的 sql 语句是

SELECT  [target],AVG([Temperature]) as Temperature,AVG([Humidity]) As Humidity,DATEADD(minute,(datediff(minute,0,[Date Time])/30)*30,0) as [Date Time],COUNT (*)                                    
FROM mytable                                    
WHERE DATEPART(minute, [Date Time]) IN (0,1,2,3,4,5,25,26,27,28,29,30,31,32,33,34,35,55,56,57,58,59)                                    
AND (CAST([Date Time] AS DATE)= '2020-09-17')                                   
AND ([target] = '1')                                    
                                    
GROUP BY [target],DATEADD(minute,(datediff(minute,0,[Date Time])/30)*30,0) ORDER BY [Date Time] ASC
output is
Target  Temperature Humidity    Date Time              (No column name)
1       21.100000   76.900000   2020-09-17 00:00:00.000      2
1       21.200000   77.300000   2020-09-17 01:00:00.000      1
1       21.133333   77.333333   2020-09-17 01:30:00.000      3
1       21.100000   77.400000   2020-09-17 02:00:00.000      1
1       21.100000   77.550000   2020-09-17 02:30:00.000      2
1       21.120000   77.640000   2020-09-17 03:00:00.000      5                      

预期的输出应该大致相同,没有列名是 1,因为应该只返回 1 个值,唯一的变化是温度和湿度不是 25-35 和 55-05 时间范围的平均值,所以温度和湿度数据应该是最接近30分钟和0分钟标记的1

【问题讨论】:

    标签: sql sql-server sql-server-2016


    【解决方案1】:

    您可以使用ROW_NUMBER()。但关键思想是将时间值四舍五入到适当的“时间组”。然后您可以使用时间组时间和观察日期时间之间的差异对行进行排序:

    SELECT  t.*                                
    FROM (SELECT t.*,
                 ROW_NUMBER() OVER (PARTITION BY t.target, v.timegrp
                                    ORDER BY ABS(DATEDIFF(SECOND, t.[Date Time], v.timegrp))
                                   ) as seqnum
          FROM mytable t CROSS APPLY
               (VALUES (DATEADD(MINUTE,
                                (DATEDIFF(MINUTE, 0, DATEADD(MINUTE, 5, t.[Date Time])) / 30) * 30,
                                0)
                       )
               ) v(timegrp)
          WHERE CAST([Date Time] AS DATE) = '2020-09-17' AND                        
                [target] = '1' AND
                v.timegrp > DATEADD(MINUTE, -5, t.[Date Time]) AND
                v.timegrp < DATEADD(MINUTE, 5, t.[Date Time])
         ) t                                  
    WHERE seqnum = 1;
    

    注意:此逻辑不适用于午夜,因为时间间隔跨越多天。为了解决这个问题,您可以将过滤移动到外部查询。我没有这样做,因为您的查询没有考虑到这一点。

    【讨论】:

    • 非常感谢您的回复,您的查询运行良好,除非日期时间间隔为 30, 00.00 00.30 并且值为 2020-09-15 23:57: 22.293 和 2020-09-15 00:01:17.233,除了你给出的答案很好之外,你能做到其中 1 个是 00.00(最接近 00.00 的 1 个)吗
    • @蒂姆。 . . 2020-09-15 不是查询的一部分。否则,时间应四舍五入到最接近的半小时。
    • hmmm 我不太确定你所说的不是查询的一部分是什么意思我使用这个查询来显示图表,对于这个问题我只是把一个日期作为一个例子,如果不是的话(CAST( [日期时间] AS DATE)= '" + TxtDate.Text + "')
    猜你喜欢
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多