在this thread上,我找到了这个例子:
DECLARE @source geography = 'POINT(-94.25 45.46)'
DECLARE @target geography = 'POINT(-94.19 45.57)'
SELECT (@source.STDistance(@target)/1000) * 0.62137
这准确地告诉我有 两点之间约8英里。这非常有帮助。但是,现在我想做的事情有点复杂。
我有一张表Criteria
,如下所示:
ID State Zip Lat Long Radius
------------------------------------------------
1 MN 56301 45.46 -94.25 25
有更多的记录,但这对我们的目的来说已经足够了。现在,我需要查询记录,其中有直接状态匹配,或直接Zip匹配,或范围匹配。所以......
DECLARE @CompareState VARCHAR(2) = NULL
DECLARE @CompareZip VARCHAR(5) = NULL
DECLARE @CompareLon DECIMAL = -94.19
DECLARE @CompareLat DECIMAL = 45.57
SELECT
*
FROM
Criteria c
WHERE
c.State = @CompareState
OR c.Zip = @CompareZip
OR (Distance between two sets of Lat and Long is <= c.Radius)
在上面的查询中,应返回ID为1的行。我正在努力学习语法。
答案 0 :(得分:1)
知道了。
DECLARE @CompareState VARCHAR(2) = NULL
DECLARE @CompareZip VARCHAR(5) = NULL
DECLARE @CompareLon DECIMAL = -94.19
DECLARE @CompareLat DECIMAL = 45.57
SELECT
*
FROM
LeadSalesCampaignCriterias c
JOIN LeadSalesCampaignCriterias c2
ON c.LeadSalesCampaignCriteriaID = c2.LeadSalesCampaignCriteriaID
AND c2.Latitude IS NOT NULL
AND c2.Longitude IS NOT NULL
WHERE
c.State = @CompareState
OR c.Zip = @CompareZip
OR
(
((geography::Point(c2.Latitude, c2.Longitude, 4326).STDistance(geography::Point(@CompareLat, @CompareLon, 4326))/1000) * 0.62137) < c.Radius
)
老实说,我不知道4326
是什么
请参阅:https://msdn.microsoft.com/en-us/library/bb933811.aspx
答案 1 :(得分:1)
我扼杀了你的答案并为了提高效率而改变了一点。
DECLARE @CompareState VARCHAR(2) = NULL
DECLARE @CompareZip VARCHAR(5) = NULL
DECLARE @CompareLon DECIMAL = -94.19
DECLARE @CompareLat DECIMAL = 45.57
-- you appear to be wanting to find things within 1 mile
-- the magic number 1609.34 is the number of meters in a mile
DECLARE @RangeDisk geography = geography::Point(@CompareLat, @CompareLon, 4326).STBuffer(1609.34);
SELECT
*
FROM
LeadSalesCampaignCriterias c
JOIN LeadSalesCampaignCriterias c2
ON c.LeadSalesCampaignCriteriaID = c2.LeadSalesCampaignCriteriaID
AND c2.Latitude IS NOT NULL
AND c2.Longitude IS NOT NULL
WHERE
c.State = @CompareState
OR c.Zip = @CompareZip
OR geography::Point(c2.Latitude, c2.Longitude, 4326).STIntersects(@RangeDisk) = 1
其他一些说明。如果您可以更改表格以预先计算地理列,那么这将使这更好,因为您不必在where子句中动态转换它(该谓词将采用new_column.STIntersects(@RangeDisk) = 1
的形式)。新列的空间索引将为查询的效率创造奇迹!
我也对自我加入感到有些困惑。 LeadSalesCampaignCriteriaID
是表中的主键吗?如果是这样,我认为加入是不必要的(很可能会影响你的表现)。
最后,在你的自我回答中,你提到不知道4326的幻数是什么。它被称为空间参考ID(也称为SRID)。从本质上讲,历史上曾多次尝试对地球进行建模。当您从外部源获得地理要素的表示时,它们将在考虑其中一个系统的情况下创建。即使您正在创建整个布料,您也需要知道测量单位是什么(例如,当您计算距离时)。您可以在sys.spatial_reference_systems
中看到SQL知道的SRID的属性。