操作数数据类型 nvarchar 对于 avg 运算符无效
Operand Datatype nvarchar is invalid for avg operator
我需要找到这个名为“Edges”的列的平均值。
其中的值类型如下:(注意:还有一堆 NULL)
EDGES
1. 1,362,797
2. 204,919
3. 26,138 948,570
4. 111,471 5,858
我已经尝试 运行 显示非空值的查询:
SELECT AVG(Edges) AS test from
(SELECT [Edges] as Edges FROM dbo.tracker
WHERE [Edges] like '%[^0-9]%') as a
我得到的错误是这样的:“操作数数据类型 nvarchar 对于 avg 运算符无效。”
平均此列的查询是什么?
您可以使用 apply
和 string_split()
:
select t.*, e.avg_edges
from t cross apply
(select avg(try_cast(s.value as numeric)) as avg_edges
from string_split(t.edges, ',') s
) e;
Here 是一个 db<>fiddle.
注意:这将忽略非数字值,例如 138 948
。但是你的问题没有解释如何处理这些值。
编辑:
如果您想要所有行的平均值:
select avg(e.edge)
from t cross apply
(select try_cast(s.value as numeric) as edge
from string_split(t.edges, ',') s
) e;
首先:如您所见,将数字存储为字符串是一个非常糟糕的主意。您应该相应地更改您的数据模型。
然后,您要查找包含非数字字符的字符串。这看起来很奇怪。这意味着从像
这样的值列表中
1,000
2,000
3000
4000
你只会考虑那些有千位分隔符并得到 (1000 + 2000 / 2) = 1500 的结果。(并且 table 中不能有非数字的字符串字符并且不代表数字,因为那样的话尝试计算平均值当然会完全失败。)
无论如何,如果您想要这个并且只要这是您的数据模型,您就必须将字符串转换为数字。不幸的是,SQL 服务器的类型转换功能至少可以说非常有限。 DBMS 应该能够隐式地从字符串转换为数字,这有效:
select '948570' + 0;
但这失败了:
select '948,570' + 0;
还有这个:
select '948,570' + 0.0;
甚至这个:
select '948570' + 0.0;
由于千位分隔符只是美化器,最好的办法是完全删除它们(使用 REPLACE
)并显式转换。但请注意,SQL 服务器在检测整数时倾向于使用小学整数数学(例如 1 / 2 = 0,而不是 0.5)。因此,尽管您的字符串表示整数,请将它们转换为 DECIMAL,而不是 INT。
SELECT AVG(CONVERT(DECIMAL, REPLACE(edges, ',', ''))) as avg_edges
FROM dbo.tracker
WHERE edges like '%[^0-9]%'
我需要找到这个名为“Edges”的列的平均值。 其中的值类型如下:(注意:还有一堆 NULL)
EDGES
1. 1,362,797
2. 204,919
3. 26,138 948,570
4. 111,471 5,858
我已经尝试 运行 显示非空值的查询:
SELECT AVG(Edges) AS test from
(SELECT [Edges] as Edges FROM dbo.tracker
WHERE [Edges] like '%[^0-9]%') as a
我得到的错误是这样的:“操作数数据类型 nvarchar 对于 avg 运算符无效。”
平均此列的查询是什么?
您可以使用 apply
和 string_split()
:
select t.*, e.avg_edges
from t cross apply
(select avg(try_cast(s.value as numeric)) as avg_edges
from string_split(t.edges, ',') s
) e;
Here 是一个 db<>fiddle.
注意:这将忽略非数字值,例如 138 948
。但是你的问题没有解释如何处理这些值。
编辑:
如果您想要所有行的平均值:
select avg(e.edge)
from t cross apply
(select try_cast(s.value as numeric) as edge
from string_split(t.edges, ',') s
) e;
首先:如您所见,将数字存储为字符串是一个非常糟糕的主意。您应该相应地更改您的数据模型。
然后,您要查找包含非数字字符的字符串。这看起来很奇怪。这意味着从像
这样的值列表中1,000 2,000 3000 4000
你只会考虑那些有千位分隔符并得到 (1000 + 2000 / 2) = 1500 的结果。(并且 table 中不能有非数字的字符串字符并且不代表数字,因为那样的话尝试计算平均值当然会完全失败。)
无论如何,如果您想要这个并且只要这是您的数据模型,您就必须将字符串转换为数字。不幸的是,SQL 服务器的类型转换功能至少可以说非常有限。 DBMS 应该能够隐式地从字符串转换为数字,这有效:
select '948570' + 0;
但这失败了:
select '948,570' + 0;
还有这个:
select '948,570' + 0.0;
甚至这个:
select '948570' + 0.0;
由于千位分隔符只是美化器,最好的办法是完全删除它们(使用 REPLACE
)并显式转换。但请注意,SQL 服务器在检测整数时倾向于使用小学整数数学(例如 1 / 2 = 0,而不是 0.5)。因此,尽管您的字符串表示整数,请将它们转换为 DECIMAL,而不是 INT。
SELECT AVG(CONVERT(DECIMAL, REPLACE(edges, ',', ''))) as avg_edges
FROM dbo.tracker
WHERE edges like '%[^0-9]%'