acos函数在区间-1< = x< = 1。
中工作有时,由于四舍五入,我得到1.00001来计算acos,然后以下where子句给我一个浮动数字错误:
where
(6371 * acos(cos(radians(@ga_where)) * cos(radians(thing_geolocation.ga_thing)) * cos(radians(thing_geolocation.go_thing) - radians(@go_where)) + sin(radians(@ga_where)) * sin(radians(thing_geolocation.ga_thing)))) < 1.5
所以,我必须将这个where子句重构成这样的东西:
where
(
6371 *
acos
(
case
when cos(radians(@latitude)) * cos(radians(thing_geolocation.ga_thing)) * cos(radians(thing_geolocation.go_thing) - radians(@longitude)) + sin(radians(@latitude)) * sin(radians(thing_geolocation.ga_thing)) > 1 then 1
when cos(radians(@latitude)) * cos(radians(thing_geolocation.ga_thing)) * cos(radians(thing_geolocation.go_thing) - radians(@longitude)) + sin(radians(@latitude)) * sin(radians(thing_geolocation.ga_thing)) < -1 then -1
else cos(radians(@latitude)) * cos(radians(thing_geolocation.ga_thing)) * cos(radians(thing_geolocation.go_thing) - radians(@longitude)) + sin(radians(@latitude)) * sin(radians(thing_geolocation.ga_thing))
end
)
) < 1.5
但是,听起来不是很好(它会导致计算距离3x,对吧?)。
我有其他想法,比如子查询或outerapply,但因为entiry查询非常复杂并且相同的字段用于其他目的,我试图在不改变整个查询的情况下解决它。
ps:我尝试使用point.distance函数,但它对null值不起作用,所以我选择保持这种方式。
有什么想法吗?
答案 0 :(得分:0)
我建议将您传递到acos
的所有内容更改为用户定义的标量值函数。在该函数中,您可以考虑大于1.0或小于-1.0的值。
通过这样做,您不必执行任何必要的数学计算。
我认为你的功能看起来像这样:
CREATE FUNCTION [dbo].[udf_GetACOSInputValueByLatLong]
(
@LatStart DECIMAL(10,6),
@LongStart DECIMAL(10,6),
@LatEnd DECIMAL(10,6),
@LongEnd DECIMAL(10,6)
)
RETURNS DECIMAL(10,6) AS
BEGIN
DECLARE @Result DECIMAL(10, 6)
SET @Result = (
cos( radians( @LatStart ) ) *
cos( radians( @LatEnd ) ) *
cos( radians( @LongEnd ) - radians(@LongStart) ) + sin( radians(@LatStart) ) *
sin( radians( @LatEnd ) )
)
IF @Result > 1.0
SET @Result = 1.0
ELSE IF @Result < -1.0
SET @Result = -1.0
RETURN (@Result)
END
然后可以使用以下内容:
where
(
6371 * acos (YourDatabase.dbo.udf_GetACOSInputValueByLatLong(
@latitude,
@longitude,
thing_geolocation.ga_thing,
thing_geolocation.go_thing))
) < 1.5