【问题标题】:Operand Datatype nvarchar is invalid for avg operator操作数数据类型 nvarchar 对 avg 运算符无效
【发布时间】:2021-03-25 07:22:06
【问题描述】:

我需要找到名为“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

我得到的错误是:“Operand data type nvarchar is invalid for avg operator.

平均该列的查询是什么?

【问题讨论】:

  • 看起来Edges 列的数据类型是字符串而不是数字。正如错误消息所述,“您不能将 nvarchar 用于 avg”
  • 您可以计算数字的平均值(例如,10 和 20 的平均值是 15),但不能计算字符串的平均值(例如,'dog' 和 'cat' 的平均值是多少?)。虽然您的字符串 '1,362,797' 可以转换为数字 1362797,但您必须告诉 DBMS 这样做。而'26,138 948,570' 不是数字,因此甚至无法转换。如果这应该是 260 亿,那么必须有一个逗号,你有一个空格。
  • @ThorstenKettner 是的。 StackOverflow 编辑了我的帖子。所有值都只是“26,138”,然后下一行是“948,570”。我尝试使用 CAST 并将它们转换为 INT,但它不起作用。我需要该列的平均值。帮忙?

标签: sql tsql average nvarchar


【解决方案1】:

首先:正如您所见,将数字存储为字符串是一个非常糟糕的主意。您应该相应地更改您的数据模型。

然后,您正在寻找包含非数字字符的字符串。这似乎很奇怪。这意味着从值列表中,例如

1,000 2,000 3000 4000

您只会考虑那些有千位分隔符并得到 (1000 + 2000 / 2) = 1500 的结果。(并且该表中不能有包含非数字字符且不代表的字符串一个数字,因为那样尝试计算平均值当然会完全失败。)

无论如何,如果您想要这个并且只要这是您的数据模型,您就必须将字符串转换为数字。不幸的是,SQL Server 的类型转换功能至少可以说非常有限。 DBMS 应该能够从字符串隐式转换为数字,这是可行的:

select '948570' + 0;

但这失败了:

select '948,570' + 0;

还有这个:

select '948,570' + 0.0;

甚至这个:

select '948570' + 0.0;

由于千位分隔符只是美化器,最好的办法是完全删除它们(使用REPLACE)并显式转换。但请注意,SQL Server 在检测整数时倾向于使用小学整数数学(例如 1 / 2 = 0,而不是 0.5)。因此,尽管您的字符串表示整数,请将它们转换为 DECIMAL,而不是 INT。

SELECT AVG(CONVERT(DECIMAL, REPLACE(edges, ',', ''))) as avg_edges
FROM dbo.tracker
WHERE edges like '%[^0-9]%'

【讨论】:

    【解决方案2】:

    您可以使用applystring_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 是一个 dbfiddle。

    注意:这会忽略非数字值,例如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;
    

    【讨论】:

    • 您好,谢谢。我想检查整个列的平均值。这意味着我最终只需要一个值作为“边缘”的平均值。 dbfiddle shared 显示每个的平均值。我不确定如何使用它。你能帮我解释一下并解决这个问题吗?
    猜你喜欢
    • 2023-04-06
    • 2013-06-14
    • 1970-01-01
    • 2020-12-19
    • 2012-08-01
    • 2022-01-07
    • 1970-01-01
    • 2017-01-24
    相关资源
    最近更新 更多