【问题标题】:CAST, SUM, CASE IssuesCAST、SUM、CASE 问题
【发布时间】:2019-08-13 08:52:25
【问题描述】:

我正在尝试在我的数据库中容纳一些包含字符串“未知”的流氓值,我想将它们设置为 0,然后将其余部分相加。但由于某种原因,这并没有发生。这是我所拥有的 -

值 - VARCHAR(30) -

     3
     0.1
     2
     16
     2
     5
     2
     Unknown
     2.4
     7
     Unknown  

这是我的演员、总和、案例

Cast(sum(case when stake = 'Unknown' then 0 else stake end) as float) as totalStake

但我收到此错误 - 将 varchar 值“0.1”转换为数据类型 int 时转换失败。

帮助!

谢谢

【问题讨论】:

  • 你为什么首先将数字数据存储为varchar?将数值数据存储为错误的数据类型存在很多问题。例如,varchar'2'大于'199''1'+'2' 等于'12'。你真的应该在这里修复你的数据类型。

标签: sql sql-server case


【解决方案1】:

您必须将赌注作为浮动:

sum(case when stake = 'Unknown' then 0.0 else cast(stake as float) end) as totalStake

【讨论】:

    【解决方案2】:

    您应该显式转换为某种数值。试试这个:

    sum(try_convert(numeric(18, 4), stake)) as totalStake
    

    您的代码至少有两个问题。首先,您的case 表达式返回一个整数(因为第一个then 有一个整数)。因此,它会尝试将stake 转换为整数,这会产生错误。

    其次,您应该对显式某种数字类型的数据进行算术运算,而不是依赖隐式转换。

    【讨论】:

      【解决方案3】:

      您可以使用 isnumeric() 尝试以下查询来检查数值数据。

      create table temp (stake VARCHAR(30))
      insert into temp values
      ('3'), ('0.1'), ('2'), ('16'), ('2'), ('5'), ('2'), ('Unknown'), ('2.4'), ('7'), ('Unknown')
      
      --Select * from temp
      
      Select sum(Cast(stake as Float)) from temp where isnumeric(stake) = 1
      

      要处理一些异常,例如 null 值或 . 值,您可以尝试这样做

      Select SUM(TRY_CAST(stake as Float)) from temp
      

      您可以找到现场演示Here

      【讨论】:

      • 我建议不要使用isnumeric。考虑到 OP 在应该包含数字数据的列中具有像 'Unknown' 这样的值,我不会把它放在它们之外以具有像 '.' 这样的值;这将导致此 SQL 出错。 TRY_CONVERTTRY_CAST 是更可靠的函数。 ISNUMERIC 可以而且确实提供了错误的答案。
      • @Larnu 但是你不能在其他数据类型列中插入未知。
      • 是的,因为 OP 应该使用NULL 来表示“未知值”。这正是NULL 是什么。
      • “OP 应该使用 NULL 来表示“未知值”。这正是 NULL 的含义。” @Larnu 我同意
      • @RaymondNijland try SELECT CASE ISNUMERIC('.') WHEN 1 THEN CONVERT(decimal(12,2),'.') ENDSELECT CASE ISNUMERIC('1.0') WHEN 1 THEN CONVERT(int,'1.0') END 注意这两个都返回错误。另请注意,ISNUMERIC('') 返回 0,但是,CONVERT(int,'') 返回 0,因为该值已成功转换。 ISNUMERIC 并不意味着该值将(或不会)转换。
      【解决方案4】:

      初始步骤是使用替换函数将“未知”字符串替换为 0,然后将列数据类型转换为允许执行聚合函数的类型,然后在此基础上执行 SUM。以下查询仅适用于“未知”字符串,如果您有除“未知”以外的其他字符串,您可能必须选择不同的方法,例如在 Replace 函数中使用 IsNumeric 并将字符串值更新为 0。

      select sum(cast((REPLACE(stake,'unknown',0))  as float)) from table
      

      【讨论】:

        【解决方案5】:

        发生这种情况是因为 SQL 在将十进制值转换为整数值时存在一些问题。 事实上,函数sum返回整数值

        我在 values1 变量上使用圆形函数解决了这个问题(对不起,表和列使用相同的名称):

         select Cast(sum(case when values1 = 'Unknown' then 0 else round(values1, 2) end)  as 
         float)as totalstrike
         from values1
        

        【讨论】:

        • “发生这种情况是因为 SQL 在将十进制值转换为整数值时遇到了一些问题。” SQL Server 在将 decimal 转换为 int 时没有任何问题;它不能做的是将decimalvarchar 表示转换为intSUM 在这里返回 int 的原因(在 OP 的问题中),是因为这是 CASE 表达式返回的数据类型,所以 SUM 返回 intSUM (Transact-SQL) - Return Types。跨度>
        • 是的,也许我表达的方式不对,我想说你在说什么
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-14
        • 1970-01-01
        • 2015-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多