我们使用多个地理点的平均值来获得平均值并将其指定为项目位置。 我现在需要追踪这些数据并以某种方式识别任何与其余数据相距太远的原始点。 我认为我需要使用STDistance,但担心要做到正确我需要2个游标来循环并比较每个点与其他点。
如果示例有助于澄清:我们需要锁定项目的GPS坐标,因此我们要求用户在项目的大致区域内按下按钮,并记录GPS协议。然后,我们将其中的5个设置为AVG(Location.Lat)+ AVG(Location.Long)。 当其中一个用户按下完成数英里之外,抛出平均值时就会出现问题,因此现在需要识别其中任何一个。
关于在SQL中执行此操作的正确/有效方法的任何想法? (处理数以百万计的条目因此担心每个项目循环2个游标会使数据库瘫痪)
答案 0 :(得分:2)
丢弃统计上无关紧要的数据对于人类来说很容易,但对于计算机来说可能有点麻烦。在您的情况下尤其如此,因为您处理的是两个维度(纬度和经度)。
我建议你看几年前写的这篇博客:Calculating Mean Median and Mode With SQL Server。
使用纬度和经度,小数点后的每个数字代表一个距离。你能做的是将纬度和经度四舍五入到一定数量的小数位,找到模式。删除与模式不同的点,然后平均剩余的未接地项。
由于您在两个维度上工作,因此您需要分别针对纬度和经度值执行此操作,因为纬度可能会偏离而经度不是(这将代表北方或南部的实际位置)。同样地,经度可能会偏离,而纬度显然是正常的。如果任何一个值都是"坏",那么你应该完全丢弃这个点。
以下是我所说的一个例子:
Declare @Temp Table(Lat Decimal(9,6), Lon Decimal(9,6))
Insert Into @Temp Values(20.12341, 10.98731)
Insert Into @Temp Values(20.12342, 10.98732)
Insert Into @Temp Values(20.12343, 10.98733)
Insert Into @Temp Values(20.12344, 10.98734)
Insert Into @Temp Values(20.12344, 10.68734) -- Latitude OK, Longitude bad
Insert Into @Temp Values(20.32344, 10.98734) -- Longitude OK, Latitude bad
Insert Into @Temp Values(20.42340, 10.68730) -- Both are bad
Select Avg(Lat), Avg(Lon)
From @Temp
Select Avg(T.Lat) As Latitude,
Avg(T.Lon) As Longitude
From @Temp T
Inner Join (
-- Calculate the mode for the latitude
Select Top 1 Convert(Decimal(9,4), Lat) As ModeOfLat
From @Temp
Group By Convert(Decimal(9,4), Lat)
Order By Count(*) DESC
) As Latitudes
On Convert(Decimal(9,4), Lat) = Latitudes.ModeOfLat
Inner Join (
-- Calculate the mode for the longitude
Select Top 1 Convert(Decimal(9,4), Lon) As ModeOfLon
From @Temp
Group By Convert(Decimal(9,4), Lon)
Order By Count(*) DESC
) As Longitudes
On Convert(Decimal(9,4), Lon) = Longitudes.ModeOfLon
如果在SQL Server Management Studio窗口中运行上面的查询,您将看到简单平均值与模式+平均值方法有很大不同。
由于这是一个基于集合的方法,因此它应该比循环/光标方法快得多。