Google 地图 SQL 服务器:计算组内异常地理数据
Google Maps SQL Server : calculating outlier geographic data within group
有 100 个供应商,每个供应商有 50 到 1000 件商品。每个供应商的物品可能靠近他们的办公室或分布在整个国家或大陆。
由于经纬度是由人工输入的,因此会出现一些错误。数据多,常量'churn',错误不易识别。
为了提高数据质量,我想确定每个供应商的异常值,以便修复它们。如果供应商的商品大部分在纽约附近,那么在加利福尼亚州的商品就属于异常值。
供应商
SupplierID int
Latitude DECIMAL(12,9)
Longitude DECIMAL(12,9)
项目
ItemID int
SupplierID int
LatLng geography
我假设我需要为此使用标准差,但是将它放入 T-SQL 中让我很头疼。
我想根据每个供应商的特定偏差输出每个供应商的异常值列表。
此代码输出项目以及每个项目与供应商办公室之间的距离。
WITH cte AS
(
SELECT
ItemID,
SupplierID,
LatLng,
LatLng.STDistance(GEOGRAPHY::Point(a.Latitude, a.Longitude, 4326))/1000 As Distance
FROM
Items v
JOIN
Suppliers a ON v.SupplierID = a.SupplierID
)
SELECT
ItemID, SupplierID, Distance
FROM cte
这是标准偏差的 SQL 功能(来自博客 post):
DECLARE @StdDev DECIMAL(5,2)
DECLARE @Avg DECIMAL(5,2)
SELECT
@StdDev = STDEV(Qty),
@Avg = AVG(Qty)
FROM Sales
SELECT
*
FROM
Sales
WHERE
Qty > @Avg - @StdDev AND
Qty < @Avg + @StdDev
我需要执行的步骤
- 计算距离
STDEV
和AVG
,GROUP BY SupplierID
- 输出项目供应商的距离大于
AVG + STDEV
的项目
这是我挠头的地方,因为这是我已经执行的多个步骤之后的多个步骤。我想我可以将我拥有的东西插入 TEMP table 然后从那里开始,但这真的是最好的方法吗?
您可以为此使用 window 函数。 AVG
和 STDEV
都可用作 window 函数
WITH Distances AS
(
SELECT
i.ItemID,
s.SupplierID,
i.LatLng,
v.SupplierLocation,
i.LatLng.STDistance(v.SupplierLocation)/1000 As Distance
FROM
Items i
JOIN
Suppliers s ON i.SupplierID = s.SupplierID
CROSS APPLY (VALUES (
GEOGRAPHY::Point(s.Latitude, s.Longitude, 4326)
)) v(SupplierLocation)
),
Averages AS (
SELECT
ItemID,
SupplierID,
LatLng,
SupplierLocation
Distance,
AVG(Distance) OVER (PARTITION BY SupplierID) AS Avg,
STDEV(Distance) OVER (PARTITION BY SupplierID) AS StDev
FROM
Distances
)
SELECT
ItemID,
SupplierID,
Distance,
Avg,
StDev
FROM
Averages
WHERE
Distance > Avg - StdDev AND
Distance < Avg + StdDev;
有 100 个供应商,每个供应商有 50 到 1000 件商品。每个供应商的物品可能靠近他们的办公室或分布在整个国家或大陆。
由于经纬度是由人工输入的,因此会出现一些错误。数据多,常量'churn',错误不易识别。
为了提高数据质量,我想确定每个供应商的异常值,以便修复它们。如果供应商的商品大部分在纽约附近,那么在加利福尼亚州的商品就属于异常值。
供应商
SupplierID int
Latitude DECIMAL(12,9)
Longitude DECIMAL(12,9)
项目
ItemID int
SupplierID int
LatLng geography
我假设我需要为此使用标准差,但是将它放入 T-SQL 中让我很头疼。
我想根据每个供应商的特定偏差输出每个供应商的异常值列表。
此代码输出项目以及每个项目与供应商办公室之间的距离。
WITH cte AS
(
SELECT
ItemID,
SupplierID,
LatLng,
LatLng.STDistance(GEOGRAPHY::Point(a.Latitude, a.Longitude, 4326))/1000 As Distance
FROM
Items v
JOIN
Suppliers a ON v.SupplierID = a.SupplierID
)
SELECT
ItemID, SupplierID, Distance
FROM cte
这是标准偏差的 SQL 功能(来自博客 post):
DECLARE @StdDev DECIMAL(5,2)
DECLARE @Avg DECIMAL(5,2)
SELECT
@StdDev = STDEV(Qty),
@Avg = AVG(Qty)
FROM Sales
SELECT
*
FROM
Sales
WHERE
Qty > @Avg - @StdDev AND
Qty < @Avg + @StdDev
我需要执行的步骤
- 计算距离
STDEV
和AVG
,GROUP BY SupplierID
- 输出项目供应商的距离大于
AVG + STDEV
的项目
这是我挠头的地方,因为这是我已经执行的多个步骤之后的多个步骤。我想我可以将我拥有的东西插入 TEMP table 然后从那里开始,但这真的是最好的方法吗?
您可以为此使用 window 函数。 AVG
和 STDEV
都可用作 window 函数
WITH Distances AS
(
SELECT
i.ItemID,
s.SupplierID,
i.LatLng,
v.SupplierLocation,
i.LatLng.STDistance(v.SupplierLocation)/1000 As Distance
FROM
Items i
JOIN
Suppliers s ON i.SupplierID = s.SupplierID
CROSS APPLY (VALUES (
GEOGRAPHY::Point(s.Latitude, s.Longitude, 4326)
)) v(SupplierLocation)
),
Averages AS (
SELECT
ItemID,
SupplierID,
LatLng,
SupplierLocation
Distance,
AVG(Distance) OVER (PARTITION BY SupplierID) AS Avg,
STDEV(Distance) OVER (PARTITION BY SupplierID) AS StDev
FROM
Distances
)
SELECT
ItemID,
SupplierID,
Distance,
Avg,
StDev
FROM
Averages
WHERE
Distance > Avg - StdDev AND
Distance < Avg + StdDev;