假设我有一个表devTest
,如下所示:
+----+------+
| id | j |
+----+------+
| 1 | 5 |
| 2 | 9 |
| 3 | 4 |
| 4 | 7 |
+----+------+
我想要一个列,指定行与j列中的平均值的偏差(以标准偏差表示)。也就是说,表格看起来像这样:
+----+------+------------+
| id | j | jDev |
+----+------+------------+
| 1 | 5 | -0.5637345 |
| 2 | 9 | 1.2402159 |
| 3 | 4 | -1.0147221 |
| 4 | 7 | 0.3382407 |
+----+------+------------+
>alter table devTest add column jDev decimal as ((j - avg(j)) / std(j));
我收到一个错误,指出聚合函数不能用于生成列的定义中:
ERROR 1901 (HY000): Function or expression 'avg()' cannot be used in the
GENERATED ALWAYS AS clause of `jDev`
制作这种专栏必须非常普遍,所以我很想知道最佳解决方案!
答案 0 :(得分:1)
此错误有意义,因为您的表格中的任何更改(例如,您添加值为0的j
)都会更新您的平均值,而这反过来会更改您生成的所有列。所以这对于查询引擎来说将是相当多的工作。
另一种解决方案是改为定义视图:
CREATE VIEW j_dev (id, j, j_dev) AS
SELECT id, j,
(j - avg(j)) / std(j) as j_dev
FROM devTest
(不确定创建视图语法,如果我错了,请纠正我)
答案 1 :(得分:1)
在标准SQL中,您可以:
select id, j, (j - avg(j) over ()) / std(j) over () as jdev
from devtest;
但MySQL不支持AVG OVER
等分析窗口函数。因此在MySQL中,您必须单独选择聚合值:
select d.id, d.j, (d.j - agg.javg) / agg.jstd as jdev
from devtest d
cross join (select avg(j) as javg, std(j) as jstd from devtest) agg;
然后创建一个视图Benjamin Crouzier在他的回答中建议:
CREATE VIEW v_devtest AS
select d.id, d.j, (d.j - agg.javg) / agg.jstd as jdev
from devtest d
cross join (select avg(j) as javg, std(j) as jstd from devtest) agg;
计算列只能从同一记录中的其他值计算其值。因此,无法使用计算列来完成您要执行的操作。