0

我有一个列名为“id”、“时间”、“值”的表,当“值”为空时,我希望它是最近邻居之间的平均值,按该 id 上的“时间”列

我的问题正是这里描述的选择最近邻居,但答案没有解释如何找到对另一列有限制的最近邻居(id 应该相同)

示例:在第二行中缺少“值”

id       | time  | value
-------------------------
11111    | 1     | 5.0
11111    | 10    | 
22222    | 7     | 32.6
33333    | 11    | 15.88
11111    | 15    | 20.0

我希望它是:

id       | time  | value
-------------------------
11111    | 1     | 5.0
11111    | 10    | 12.5*
22222    | 7     | 32.6
33333    | 11    | 15.88
11111    | 15    | 20.0

为 (20.0 + 5.0) / 2 = 12.5

在 MySQL 中如何获取?

4

3 回答 3

0

只是加入自己,但要注意没有 NEXT_VALUE

SELECT ID_,
   TIME_,
   CASE
      WHEN VALUE_ IS NULL THEN (LAST_VALUE + NEXT_VALUE) / 2
      ELSE VALUE_
   END AS REAL_VALUE
FROM (SELECT ROW_NUMBER () OVER (PARTITION BY ID_ ORDER BY TIME_ DESC)
              NOW_ROW_NUM,
           ID_,
           TIME_,
           VALUE_
      FROM TESTTABLE)
   LEFT JOIN (SELECT (ROW_NUMBER ()
                         OVER (PARTITION BY ID_ ORDER BY TIME_ DESC))
                     - 1
                        LAST_ROW_NUM,
                     ID_ AS LAST_ID,
                     VALUE_ AS LAST_VALUE
                FROM TESTTABLE)
      ON ID_ = LAST_ID AND NOW_ROW_NUM = LAST_ROW_NUM
   LEFT JOIN (SELECT (ROW_NUMBER ()
                         OVER (PARTITION BY ID_ ORDER BY TIME_ DESC))
                     + 1
                        NEXT_ROW_NUM,
                     ID_ AS NEXT_ID,
                     VALUE_ AS NEXT_VALUE
                FROM TESTTABLE)
      ON ID_ = LAST_ID AND NOW_ROW_NUM = NEXT_ROW_NUM
于 2019-03-30T19:22:22.270 回答
0

只需使用lead()lag()。最简单的答案是:

selet t.*
      (case when value is null
            then ( lag(value) over (partition by id order by time) + lead(value) over (partition by id order by time) ) / 2
            else value
       end) as new_value
from t;

这不适用于第一个或最后一个值。您可以改为使用:

selet t.*
      (case when value is null
            then ( avg(value) over (partition by id order by time rows between 1 preceding and 1 following)
            else value
       end) as new_value
from t;

这会根据前后行中的可用数据计算平均值。

于 2019-03-30T22:29:43.667 回答
0

假设它time定义了顺序并且是唯一的(为此需要一个唯一的列和一个定义顺序的列),一种方法是使用子查询来获取value记录的顶部(底部),使用较小(较大)timeORDER BYLIMIT

SELECT t1.id,
       t1.time,
       coalesce(t1.value,
                ((SELECT t2.value
                         FROM elbat t2
                         WHERE t2.id = t1.id
                               AND t2.time < t1.time
                         ORDER BY t2.time DESC
                         LIMIT 1)
                 +
                 (SELECT t2.value
                         FROM elbat t2
                         WHERE t2.id = t1.id
                               AND t2.time > t1.time
                         ORDER BY t2.time ASC
                         LIMIT 1)
                )
                /
                2) value
       FROM elbat t1;

db<>小提琴

但这只能填补一排宽的空白。如果可能有更大的差距,您必须定义这些行的下一个非空邻居是什么。

于 2019-03-30T19:01:51.477 回答