平均浮动不一致

时间:2015-10-24 20:08:20

标签: sql-server tsql sql-server-2012 floating-accuracy

选择返回23,000行左右 除外将返回60到200行(而不是相同的行)
除非选择a

,否则应该返回0,因为它是选择a

PK:[docSVenum1]。[enumID],[docSVenum1]。[valueID],[FTSindexWordOnce]。[wordID]

[tf]是一个浮点数而且我得到的浮点数并不准确 但我天真地认为avg(浮动)是可重复的 平均(浮动)确实似乎是可重复的

解决方案是什么?
TF介于0和1之间,我只需要5位有效数字 我只需要avg(TF)运行相同的数字运行
十进制(9,8)给了我足够的精度,如果我转换为十进制(9,8),则正确返回0
我可以将[TF]更改为十进制(9,8)但是它会有点工作和很多回归测试,因为某些测试使用[tf]需要一天才能运行
将[TF]更改为十进制(9,8)是最佳解决方案吗?

  SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
       , avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
    FROM [docSVenum1] 
    JOIN [docFieldLock] 
           ON [docFieldLock].[sID] = [docSVenum1].[sID] 
          AND [docFieldLock].[fieldID] = [docSVenum1].[enumID] 
          AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */ 
    JOIN [FTSindexWordOnce] 
           ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]

except 

  SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
       , avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
    FROM [docSVenum1] 
    JOIN [docFieldLock] 
           ON [docFieldLock].[sID] = [docSVenum1].[sID] 
          AND [docFieldLock].[fieldID] = [docSVenum1].[enumID] 
          AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */ 
    JOIN [FTSindexWordOnce] 
           ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID] 

order by [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]

在这种情况下,tf是tf-idf的术语频率 标准化是主观的,不需要太多精确度 平均值(tf)需要从选择到选择一致或结果不一致
在带连接的单个选择中,我需要一致的平均值(tf)
使用小数和低精度的tf得到了一致的结果

1 个答案:

答案 0 :(得分:3)

这非常类似于: SELECT SUM(...) is non-deterministic when adding the column-values of datatype float

问题是,如果数据类型不准确(FLOAT/REAL),浮点算术运算的顺序很重要。连接演示:

DECLARE @fl FLOAT = 100000000000000000000
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
    SET @fl = @fl + CONVERT(float, 5000)
    SET @i = @i + 1
END
SET @fl = @fl - 100000000000000000000
SELECT CONVERT(NVARCHAR(40), @fl, 2)
-- 0.000000000000000e+000


DECLARE @fl FLOAT = 0
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
    SET @fl = @fl + CONVERT(float, 5000)
    SET @i = @i + 1
END
SET @fl = @fl + 100000000000000000000
SET @fl = @fl - 100000000000000000000
SELECT @fl
-- 507904

LiveDemo

可能的解决方案:

  • CAST所有准确数据类型的参数,如DECIMAL/NUMERIC
  • 更改表并将FLOAT更改为DECIMAL
  • 您可以尝试强制查询优化器以相同的顺序计算总和。
  

好消息是,当稳定的查询结果对您而言很重要时   应用程序,您可以通过阻止强制命令相同   与 OPTION(MAXDOP 1)的并行性。

看起来初始链接已经死了。 WebArchive