【问题标题】:Aggregation and average value with interval in SQLSQL中带间隔的聚合和平均值
【发布时间】:2021-01-20 19:28:23
【问题描述】:

我有一张表,里面有这样的数据集

Time_1 Temperature
2020-11-20 12:05:15.520 75
2020-11-20 12:06:50.297 111
2020-11-20 12:08:10.513 147
2020-11-20 12:11:10.593 72
2020-11-20 12:10:46.000 62
2020-11-20 12:15:15.263 171
2020-11-20 12:16:34.577 238
2020-11-20 12:16:45.577 284
2020-11-20 12:18:08.373 304
2020-11-20 12:20:57.030 299
2020-11-20 12:22:21.670 313
2020-11-20 12:34:43.733 100

我想根据另一个时间戳(time_2)的时间间隔(在大多数情况下是 10 分钟间隔)对上述温度数据进行平均,并有类似的东西

Time_2 Records_in_interval Av_Temp
2020-11-20 12:05:19.000 6 106.33
2020-11-20 12:15:19.000 5 287.6
2020-11-20 12:25:19.000 1 100

我面临的一个问题是间隔并不总是 10 分钟。 这是我到目前为止所做的,但它不起作用。

DECLARE @StartDate nvarchar(20)
DECLARE @EndDate nvarchar(20)
     
    SET @StartDate ='2020-11-20 12:00:00'
    SET @EndDate =  '2020-11-20 23:59:59'

SELECT  
      [Date1]= CONVERT(datetime, t2.[time_2], 20),
      DATEADD(MINUTE, DATEDIFF(MINUTE,  t2.[time_2], t1.[time_1]) / 10 * 10,t2.[time_2]) AS [date_truncated],
      COUNT(*) AS [records_in_interval],
      AVG(t1.[temperature]) AS [Av_Temp] 

FROM fix.dbo.main_db2 t2
    LEFT JOIN fix1.dbo.main_db1 t1 on DATEADD(MINUTE, DATEDIFF(MINUTE, t2.[time_2], t1.[time_1]) / 10 * 10,t2.[time_2])=t2.[time_2]
    
    WHERE 
     CONVERT(datetime, t2.[time_2], 20)  BETWEEN CONVERT(datetime, @StartDate , 20) AND CONVERT(datetime, @EndDate , 20)
    
GROUP BY 
    DATEADD(MINUTE, DATEDIFF(MINUTE, t2.[time_2], t1.[time_1]) / 10 * 10, t2.[time_2]),
    t2.[time_2]
ORDER BY 
[date_truncated]

【问题讨论】:

  • 这是两个不同的表吗?目前尚不清楚您真正要问的是什么。
  • 你做了哪些研究?你试过什么?你在哪里卡住了?
  • 您使用什么逻辑在第一行中生成值“2020-11-20 12:05:19.000”?它不存在于您的表中。此外,“在大多数情况下 10 分钟间隔”这句话作为编写代码的基础似乎有点过于灵活了。你能扩展一下这个意图吗?
  • 你是对的,我没有正确解释。是的,那是两张不同的桌子。
  • @SMor Time_2 每 10 分钟增加一次,但在极少数情况下,它可能会以更长或更短的时间间隔增加。 time_2 中的每个间隔代表该时间段内的平均测量值。所以我想要做的是对于 time_2 的每个时间间隔,查看第一个表上存在哪些测量值并将它们平均。例如在 12:05:19 和 12:15:19 之间有 5 次温度测量。

标签: sql sql-server tsql average


【解决方案1】:

如果您有第二张带时间的表,那么您可以使用join 和聚合:

select t2.time_2, count(temperature), avg(temperature)
from (select t2.*, lead(time_2) over (order by time_2) as next_time_2
      from table2 t2
     ) t2 left join
     table1 t1
     on t1.time_1 >= t2.time_2 and
        t1.time_1 < t2.next_time_2
group by t2.time_2;

编辑:

认为您可以为此使用相关子查询:

select t2.time_2, count(temperature), avg(temperature)
from (select t2.*,
             (select min(tt2.time_2)
              from table2 tt2
              where tt2.time_2 > t2.time_2
             ) as next_time_2
      from table2 t2
     ) t2 left join
     table1 t1
     on t1.time_1 >= t2.time_2 and
        t1.time_1 < t2.next_time_2
group by t2.time_2;

但老实说,我不记得 SQL Server 2000 有什么限制了。在这一点上它完全是过时的。

【讨论】:

  • 'lead' 功能有什么替代品吗?因为我使用的数据库存在兼容性问题。谢谢
  • @theo13 。 . . 所有支持的 SQL Server 版本都支持lead()。那么问题来了:您为什么使用不受支持的 SQL Server 版本?如果是这样,您真正使用的是什么版本?
  • 我从中获取数据的数据库具有兼容级别 SQL Server 2000 (80),并且从我发现的搜索结果中,您需要具有兼容级别 110 才能使用领先功能。如果我错了,请纠正我,因为我是 sql 新手。
  • @theo13 。 . .我只是不想在 SQL Server 2000 中尝试这样做。
  • 很高兴知道,任何其他建议/方法将不胜感激
【解决方案2】:

如果你只有第一个表,你可以使用 union 得到所有三个结果。

SELECT '2020-11-20 12:05:19.000' AS Time_2,
COUNT(*) AS Records_in_Interval,
AVG(temp) AS Avg_Temp
FROM #temp
WHERE time > '2020-11-20 12:05:19.000' AND time < '2020-11-20 12:15:19.000'
UNION ALL
SELECT '2020-11-20 12:15:19.000' AS Time_2,
COUNT(*) AS Records_in_Interval,
AVG(temp) AS Avg_Temp
FROM #temp
WHERE time > '2020-11-20 12:15:19.000' AND time < '2020-11-20 12:25:19.000'
UNION ALL 
SELECT '2020-11-20 12:25:19.000' AS Time_2,
COUNT(*) AS Records_in_Interval,
AVG(temp) AS Avg_Temp
FROM #temp
WHERE time > '2020-11-20 12:25:19.000'

谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-20
    • 2021-11-11
    • 2021-05-15
    • 2021-08-12
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多