带计算列的简单SELECT查询返回错误

时间:2017-04-21 08:18:58

标签: sql-server select

我有一个问题:

use [Some_Database];
go
select toip 10 IDEVENT,
    COUNT(*)
from [AL_PROTOCOL]
    group by IDEVENT
    order by Quanity desc
go

在输出中,我得到结果

IDEVENT     Quanity
664         4,037787E+07
566         2,124254E+07
438         1,248467E+07
294         9926404 
564         9777449
436         5784661 
310         5709771 
428         5161083 
432         5154893 
434         5150308 

然后,我尝试使用(*60 / 1,000,000)

计算第二个CONVERT (real (100), COUNT(*)*60/1000000, 2) as 'Size, Mb'

下一步:

use [Some_Database];
go
select top 10 IDEVENT,
    COUNT(*),
    CONVERT (real (100), COUNT(*)*60/1000000, 2) as 'Size, Mb'
from [AL_PROTOCOL]
    group by IDEVENT
    order by Quanity desc
go

在此之后,我收到此错误

  

8115'将表达式转换为int类型的算术溢出错误   的数字'

Technet解释说,当列中的值过度增加整数类型的最大大小时会发生这种错误。但是,为什么它不能在REAL类型中转换? 此外,这个问题通过替换' * 60 / 1,000,000'在' / 1,000,000 * 60',但我的兴趣不满意。

我做错了什么?感谢

2 个答案:

答案 0 :(得分:2)

如果你将一个非常大的数字乘以60,你将得到一个更大的数字,增加了算术溢出的可能性。你之后将它除以1,000,000的事实为时已晚,你已经试图生成一个太大而无法继续的数字。

但是,当你在乘以60之前先将它除以1,000,000,那么你总是会得到一个较小的数字,所以你永远不会得到算术溢出。

此外,对于您的CONVERT,您在整个结果中执行此操作,并且计算中的所有数字都是INT类型,因此它将生成INT之前转换。

COUNT(*)*60/1000000 -- COUNT(*) is an INT, as well as the other numbers

如果您更改CONVERT \ CAST的顺序,则应该有效。

DECLARE @number AS INT 
SET @number = 123456789

-- this doesn't work
SELECT CAST((@number * 60) AS REAL(100))
-- this does
SELECT CAST(@number AS REAL(100)) * 60

答案 1 :(得分:2)

仔细查看您要求DBMS执行的操作顺序。 CONVERT (real (100), COUNT(*)*60/1000000, 2)表示:

  1. COUNT(*)
  2. result * 60
  3. result / 1000000
  4. CONVERT (real (100), result, 2)
  5. 在第4步之前,该值仍然是整数,因此如果COUNT(*) * 60高于最大可表示整数,则会出现溢出错误。

    由于*/具有相同的优先级,因此您找到的解决方法是CONVERT (real (100), COUNT(*)/1000000*60, 2),这意味着:

    1. COUNT(*)
    2. result / 1000000
    3. result * 60
    4. CONVERT (real (100), result, 2)
    5. 我们仍在对整数进行数学运算,但现在我们永远不会溢出,因为我们在乘法之前除以。

      但你真正想要的是对浮点值进行所有数学运算:

      1. COUNT(*)
      2. CONVERT (real (100), result, 2)
      3. result * 60
      4. result / 1000000
      5. 为此,您只需要交换嵌套,以便直接转换COUNT(*)结果,然后应用数学:CONVERT (real (100), COUNT(*), 2) * 60 / 1000000