我的数据形成如下:
+----------+-------+-------+
| DAY | VALUE | Name |
+----------+-------+-------+
| 01/01/14 | 1030 | BOB
| 01/02/14 | 1020 | BOB
| 01/03/14 | 1080 | BOB
| 01/04/14 | 1090 | BOB
| 01/05/14 | 1040 | BOB
| 01/08/14 | 1030 | BOB
| 01/11/14 | 4030 | BOB
| 01/12/14 | 5000 | BOB
| 01/13/14 | 6000 | BOB
| 01/14/14 | 1096 | BOB
| 01/14/14 | 1200 | MIKE
| 01/15/14 | 1040 | MIKE
| 01/16/14 | 1600 | MIKE
| 01/17/14 | 1070 | MIKE
| 01/18/14 | 1340 | MIKE
| 01/19/14 | 1060 | MIKE
| 01/01/14 | 6000 | JANE
| 01/02/14 | 1700 | JANE
| 01/03/14 | 1070 | JANE
| 01/04/14 | 8000 | JANE
+----------+-------+------+
对于每个名称,2014年1月1日至2014年1月1日(1个月)之间的日期需要有一行。正如你所看到的,Bob,Mike和Jane(虽然在我的真实数据库中有数千个名字)都是在这个时间段之间缺少日期。我想以某种方式通过插值插入缺少的行。例如Bob缺少2014年6月1日和01/07/14。我希望通过添加这两个日期进行插值,然后将值作为两个字段之间的平均值,这样这两个缺失的字段都将具有值((1040 + 1030)/ 2)= 1035.如果没有之前的数据就像MIKE一样(从2014年1月14日开始)我希望所有新行现在都具有01/14/14值。我尝试了各种不同的技术,例如使用coalesce命令,游标,但无法使其工作。此外,我没有设置这些EXACT值,如果有某种数学库可以插值我也会对此开放。感谢。
答案 0 :(得分:1)
您有两个问题,即生成行并插值。您可以使用此SQL生成行:
select d.day, n.name, t.value
from (select distinct name from table t) n cross join
(select distinct day from table t) d left outer join
table t
on t.name = n.name and t.day = d.day;
进行插值很麻烦。您可以使用变量和多重排序来完成此操作。这是逻辑:
select day, name, value, prev_value,
@value as next_value,
@value := if(@name = name and value is not null, value, @value),
@name := name
from (select d.day, n.name, t.value,
@value as prev_value,
@value := if(@name = name and value is not null, value, @value),
@name := name
from (select distinct name from table t) n cross join
(select distinct day from table t) d left outer join
table t
on t.name = n.name and t.day = d.day cross join
(select @name := '', @value := NULL) vars
order by n.name, d.day
) t cross join
(select @name := '', @value := NULL) vars
order by n.name, d.day desc;
这可能对您有用,但它依赖于MySQL在每个select
中按顺序评估表达式(用于变量赋值)。您可以使语法更复杂以解决此问题,但这会隐藏逻辑。您现在可以实现所需的逻辑:
select day, name,
(case when value is not null then value
when prev_value is not null and next_value is not null
then (prev_value + next_value) / 2
when prev_value is null then next_value
else prev_value
end) as value
from (<previous query here>) t;