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
4

2 に答える 2

1

GetDist が緯度/経度値のペア間の距離を計算しているようです。私はこれについて多くの経験を持っています。このような GetDist 関数のほとんどは、アーク コサイン関数 "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

これで元の問題が解決しない場合でも、少なくとも奇妙な浮動小数点数/精度の問題から保護されます。

于 2013-02-20T16:48:21.683 に答える
0

問題は無効な操作ですか、それとも「データ型 varchar から数値への変換エラー」のようなものですか? これは、数値データが文字列として格納されている場合によくある問題です。文字列が正しく見える場合は機能しますが、それ以外の場合は失敗します。

へのすべての引数getDist()は正しい型ですか? 戻り値は数値ですか?

より高いレベルでのフィルタリングにより、問題の原因となっている悪い値が除外されると思います。

于 2013-02-20T15:27:34.207 に答える