我正在编写一个汇总一些常见数据的查询。基本上,我试图确定资源何时被使用。
不幸的是,我的查询返回了一个错误:
将表达式转换为数据类型tinyint的算术溢出错误。
insert into Utilization
select resource
,timesegment
,case when min(uc.casemain_id) is null then 0 else count(uc.casemain_id) end as InUse
from ...
group by resource, timesegment
错误发生在InUse
上,目标列是一个小int。我已独立运行查询,并且计数的最小值和最大值为0和4。
select min(InUse), max(InUse)
from (... the query above ...)
返回:0,4
有关为何发生这种情况的任何建议?
导致错误的组合示例:
CREATE TABLE Usage(
[Resource] [varchar](50) NULL,
[TimeSegment] [datetime] NULL,
[InUse] [tinyint] NULL
);
CREATE TABLE TimeMap(
[TimeSegment] [datetime] NULL,
[Resource] [varchar](50) NULL,
[Case] [varchar](50) null,
[Usage] [tinyint] NULL
);
CREATE PROCEDURE [dbo].[BuildTimeUsageMap] AS
BEGIN
truncate table Utilization;
insert into Utilization
select resource
,timesegment
,count(uc.casemain_id) as InUse
from timemap
group by resource, timesegment
END;
exec BuildTimeUsageMap;
我已将select语句更改为简化(将count(*)
更改为count(uc.casemain_id)
确实返回非空值的计数,谢谢@ughai)。此外,我已通过将InUse的数据类型更改为smallint
来解决此问题。
将数据类型更改为smallint
会导致问题消失,但这并不能解释为什么它首先不起作用。
select min(InUse), max(InUse) from Usage
结果:0,4
这两者都应该适合tinyint
答案 0 :(得分:2)
我相信你违反了SQL Server的illogical errors(它以不同的顺序对SQL语句的logical processing order执行某些操作,并且这会引发以前不会产生的错误它遵循逻辑顺序。)
在这种情况下,您唯一真正的选择是将查询拆分为多个查询。请注意,子查询/ CTE不足以保证优化器不会充分移动以引起这些错误。
所以我会:
a)使用比真实表更宽松的类型约束创建临时表(即使用int
或bigint
而不是tinyint
)并填充它。此查询应该是执行任何聚合和任何过滤器的查询。
b)(可选)运行查询,专门针对超出范围的值并针对任何找到的内容提出特定的错误消息
c)INSERT
从临时表到真实表。
答案 1 :(得分:0)
假设InUse
是TINYINT,查询中可能有超过255条记录,因此溢出是COUNT(uc.casemain_id)
返回高于255的值.MIN和MAX不计算记录 - 查询中的最高和最低值。用COUNT(1)替换第二个查询,保持相同的组,以确认行数超过TINYINT最大值。
答案 2 :(得分:0)
试试这个:
And I logout