一段时间内分组的值的平均值

时间:2020-06-03 10:05:22

标签: sql-server tsql

我想找到分组值的平均值 使用规则(if time(n+1) - time(n) < 40 minutes)和功能

<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}
</style>
<table class="tg">
<thead>
  <tr>
    <th class="tg-0pky">feature</th>
    <th class="tg-0pky">value</th>
    <th class="tg-0pky">time</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,76</td>
    <td class="tg-0pky">20200508 11:13:06</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,69</td>
    <td class="tg-0pky">20200508 11:13:13</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,94</td>
    <td class="tg-0pky">20200508 11:13:20</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,73</td>
    <td class="tg-0pky">20200508 11:13:27</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,79</td>
    <td class="tg-0pky">20200508 12:16:55</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,76</td>
    <td class="tg-0pky">20200508 12:17:03</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">60,1</td>
    <td class="tg-0pky">20200508 12:17:10</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">59,95</td>
    <td class="tg-0pky">20200508 12:17:18</td>
  </tr>
  <tr>
    <td class="tg-0pky">Diameter</td>
    <td class="tg-0pky">60,02</td>
    <td class="tg-0pky">20200508 12:17:36</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,1</td>
    <td class="tg-0pky">20200508 05:23:30</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,08</td>
    <td class="tg-0pky">20200508 05:23:35</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,04</td>
    <td class="tg-0pky">20200508 05:23:40</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,06</td>
    <td class="tg-0pky">20200508 05:23:46</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,16</td>
    <td class="tg-0pky">20200508 05:23:52</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,69</td>
    <td class="tg-0pky">20200508 06:03:05</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,65</td>
    <td class="tg-0pky">20200508 06:03:13</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,64</td>
    <td class="tg-0pky">20200508 06:03:18</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,39</td>
    <td class="tg-0pky">20200508 06:03:24</td>
  </tr>
  <tr>
    <td class="tg-0pky">Weight</td>
    <td class="tg-0pky">9,44</td>
    <td class="tg-0pky">20200508 06:03:29</td>
  </tr>
</tbody>
</table>

我试图做这样的事情:

我尝试过类似的事情:

SELECT avg(ISNULL(Value,0)), feature FROM V_Value GROUP BY (SELECT avg(Value) from V_Value t1, V_Value t2 where DATEDIFF(minute,t1.DateMis+t1.HourMis,t2.DateMis+t2.HourMis) <= '40' ) order by feature

但是它不起作用。返回有关group by子句的错误

分组应为:

enter image description here

因为他每40分钟对同一功能的值进行分组

结果应该是:

Diameter | 59,78
Diameter | 59,924
Weight   | 9,088
Weight   | 9,562

1 个答案:

答案 0 :(得分:0)

我花了一些时间解决这个问题,但是经过一番谷歌搜索和尝试之后,我达到了这个解决方案。

它将日期时间向下舍入到所需的精度(在这种情况下为40分钟),并将此舍入的时间用作分组列。

SELECT 
     [rounded_time]
    ,[feature]
    ,AVG([value]) AS [value]
FROM (
    SELECT
         [time]
        ,DATEADD(mi, DATEDIFF(mi, 0, [time])/40*40, 0) as [rounded_time]
        ,[feature]
        ,[value]
    FROM V_Value
) as x

要解释其作用,您可以看到以下代码示例,它将比word更好地解释

DECLARE @SampleData TABLE
(TimeCol Datetime
)

INSERT INTO @SampleData VALUES
     ('2020-06-04 17:00:00'),('2020-06-04 17:05:00'),('2020-06-04 17:10:00')
    ,('2020-06-04 17:15:00'),('2020-06-04 17:20:00'),('2020-06-04 17:25:00')
    ,('2020-06-04 17:30:00'),('2020-06-04 17:35:00'),('2020-06-04 17:40:00')
    ,('2020-06-04 17:45:00'),('2020-06-04 17:50:00'),('2020-06-04 17:55:00')
    ,('2020-06-04 18:00:00'),('2020-06-04 18:05:00'),('2020-06-04 18:10:00')
    ,('2020-06-04 18:15:00'),('2020-06-04 18:20:00'),('2020-06-04 18:25:00')
    ,('2020-06-04 18:30:00'),('2020-06-04 18:35:00'),('2020-06-04 18:40:00')

SELECT 
     [TimeCol] AS [Source_Time]
    ,DATEDIFF(mi, 0, [TimeCol]) AS [MinSince1900] --minutes since 1900-01-01 00:00
    ,DATEDIFF(mi, 0, [TimeCol])/40*40 AS [MinSince1900_Rounded] --integer divison truncates the decimal part, therefore the result is always rounded down (in this case in blocks of 40min)
    ,DATEADD(mi, DATEDIFF(mi, 0, [TimeCol])/40*40, 0) AS [Rounded_Time]--add the above minutes back to 1900-01-01 00:00 and you get your grounded datetime
FROM @SampleData