2013-02-20 41 views
0

我運行SQL Server 2008數據庫,我使用的Web應用程序下面的查詢,但調試錯誤點我很直接運行在管理工作室查詢。隨機浮點錯誤與子查詢訂單

我收到以下錯誤 - 發生無效的浮點操作。運行此查詢時。

select p.Id as Id, p.CatId as CatId, p.MetaName as MetaName ,p.Active as Active,p.HasChildren as HasChildren ,p.Mlevel as Mlevel ,p.ParentId as ParentId ,p.Type as Type, p.VOrder as VOrder, p.UrlOrder as UrlOrder, Count('*') as VCount 
from MetaDataValues as m 
left join MetaData as p on m.MetaDataId = p.Id 
left join Adverts as a on m.AdvertId = a.Id 
where a.Status = 1 
and a.ExpDate > current_timestamp and 
m.AdvertId in 
(select m2.AdvertId from MetaDataValues as m2 left join MetaData as p2 on m2.MetaDataId = p2.Id where p2.MetaName = 'meta1' 
and m.AdvertId in (select m3.AdvertId from MetaDataValues as m3 left join MetaData as p3 on m3.MetaDataId = p3.Id where p3.MetaName = 'meta2' 
and m.AdvertId in (select m4.AdvertId from MetaDataValues as m4 left join MetaData as p4 on m4.MetaDataId = p4.Id where p4.MetaName = 'meta3' 
and m.AdvertId in (select ad9.Id from Adverts as ad9 where dbo.GetDist(ad9.X,ad9.Y,ad9.Z,52.9131514,-2.9313405) < 969)))) 
group by p.Id, p.CatId, p.MetaName,p.Active,p.HasChildren,p.Mlevel,p.ParentId,p.Type, p.VOrder, p.UrlOrder 

解釋它是導致問題的GetDist功能,如果我在子查詢這個移動到頂部水平與查詢運行正常?這不是一個理想的,因爲構建這個查詢的代碼是以某種方式編碼的,我不想改變它。所以這裏是查詢的工作,完全相同,但不同的順序!

select p.Id as Id, p.CatId as CatId, p.MetaName as MetaName ,p.Active as Active,p.HasChildren as HasChildren ,p.Mlevel as Mlevel ,p.ParentId as ParentId ,p.Type as Type, p.VOrder as VOrder, p.UrlOrder as UrlOrder, Count('*') as VCount 
from MetaDataValues as m 
left join MetaData as p on m.MetaDataId = p.Id 
left join Adverts as a on m.AdvertId = a.Id 
where a.Status = 1 
and a.ExpDate > current_timestamp and 
m.AdvertId in 
(select m2.AdvertId from MetaDataValues as m2 left join MetaData as p2 on m2.MetaDataId = p2.Id where p2.MetaName = 'meta1' 
and m.AdvertId in (select ad9.Id from Adverts as ad9 where dbo.GetDist(ad9.X,ad9.Y,ad9.Z,52.9131514,-2.9313405) < 969) 
and m.AdvertId in (select m3.AdvertId from MetaDataValues as m3 left join MetaData as p3 on m3.MetaDataId = p3.Id where p3.MetaName = 'meta2' 
and m.AdvertId in (select m4.AdvertId from MetaDataValues as m4 left join MetaData as p4 on m4.MetaDataId = p4.Id where p4.MetaName = 'meta3'))) 
group by p.Id, p.CatId, p.MetaName,p.Active,p.HasChildren,p.Mlevel,p.ParentId,p.Type, p.VOrder, p.UrlOrder 



GetDist code 

USE [MVC] 
GO 
/****** Object: UserDefinedFunction [dbo].[GetDist] Script Date: 02/20/2013 17:05:00 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER FUNCTION [dbo].[GetDist] 
    (
    @xaxis float, 
    @yaxis float, 
    @zaxis float, 
    @CenterLat float, 
    @CenterLon float 
    ) 
RETURNS float 
AS 
    BEGIN 

declare @CntXAxis float 
declare @CntYAxis float 
declare @CntZAxis float 
declare @EarthRadius float 

set @EarthRadius = 3961 
set @CntXAxis = cos(radians(@CenterLat)) * cos(radians(@CenterLon)) 
set @CntYAxis = cos(radians(@CenterLat)) * sin(radians(@CenterLon)) 
set @CntZAxis = sin(radians(@CenterLat)) 

return (@EarthRadius * acos(@XAxis*@CntXAxis + @YAxis*@CntYAxis + @ZAxis*@CntZAxis)) 


    END 
+0

你可以發佈GetDist函數的代碼嗎? – 2013-02-20 16:39:37

回答

1

它看起來像GetDist可以計算一對緯度/經度值的之間的距離。我有很多這方面的經驗。大多數GetDist函數使用Arc Cosine函數「ACos」。此函數的參數限制在-1到1的範圍內。如果嘗試將超出此範圍的值傳遞給SQL Server,將會出現域錯誤。如果您的GetDist函數使用CLR函數,則錯誤將位於.NET代碼中,並且會有稍微不同的消息。

當處理浮標時,您必須注意奇怪的舍入問題。例如,如果您的計算返回值爲1.00000000000001,並將其傳遞給ACos函數,則會出現錯誤。

有很多猜測這裏,我可以完全關閉基地,但請考慮這一點,並花幾分鐘時間做一些研究。

根據您GetDist功能上面貼,我會建議一個比較小的變化:

ALTER FUNCTION [dbo].[GetDist] 
    (
    @xaxis float, 
    @yaxis float, 
    @zaxis float, 
    @CenterLat float, 
    @CenterLon float 
    ) 
RETURNS float 
AS 
    BEGIN 

declare @CntXAxis float 
declare @CntYAxis float 
declare @CntZAxis float 
declare @EarthRadius float 
declare @Temp float 

set @EarthRadius = 3961 
set @CntXAxis = cos(radians(@CenterLat)) * cos(radians(@CenterLon)) 
set @CntYAxis = cos(radians(@CenterLat)) * sin(radians(@CenterLon)) 
set @CntZAxis = sin(radians(@CenterLat)) 

Set @Temp = @XAxis*@CntXAxis + @YAxis*@CntYAxis + @ZAxis*@CntZAxis 
If @Temp > 1 
    Set @Temp = 1 
Else If @Temp < -1 
    Set @Temp = -1 

return (@EarthRadius * acos(@Temp)) 

    END 

即使這並沒有解決原來的問題,它至少會保護你的怪異浮動/精度問題。

+0

我剛貼出上面getdist,是的,你是對的功能是什麼正確做和我明白,範圍被限制爲-1到1.奇怪的是,如果我重新排序的子查詢,即先距離一個,它的工作!所以它排隊數據集。此外,如果我刪除其他subqueriers之一,它也可以。 – andyewebb 2013-02-20 17:06:12

+0

無論你寫什麼命令你的查詢。 T-SQL查詢優化器將評估整個查詢並確定執行查詢的最佳順序。我會說這是一個簡單的,「你有一種幸運的方式,而不幸的是另一種方式」。解決此問題的唯一方法是確定潛在問題並在此處進行修復。希望我爲這個功能提出的改變將會照顧到這個問題。 – 2013-02-20 18:57:09

+0

謝謝你解決了這個問題,我不會試着去理解爲什麼,再次感謝。 – andyewebb 2013-02-24 16:30:53

0

問題是一個無效的操作或更類似於「將數據類型varchar轉換爲數字」的問題?當數字數據被存儲爲字符串時,這是一個相當常見的問題。它在字符串看起來正確時有效,但在其他時間失敗。

是否所有參數的正確類型的getDist()?返回值是一個數字嗎?

我猜想,在更高層次上篩選過濾掉那些導致問題的錯誤值。

+0

是的,他們是正確的和float類型的,它的工作原理時,有更小,其中這樣的條款更大的數據集,所以我不認爲它可以是數據問題 – andyewebb 2013-02-20 15:34:34