这是我的疑问难题: - 我有一张客户表,其中包含经度和纬度 邮政编码。 - 我有一张经度和供应商的供应商表 纬度为他们的邮政编码。 - 之间没有任何关系 表。 - 我有一个用户定义函数来计算距离 在两组经度和纬度之间。
我有以下查询可以显示(最多)给定客户50英里范围内最近的三个供应商(dbo.latlngdistance是用户定义的函数):
select top 3 dname1, dcity, dstate, dzip, dbo.latlngdistance(dlr.latitude, dlr.longitude,
(select lat from homeowner where ho_identifier = 16),
(select lng from homeowner where ho_identifier = 16)) AS SortDistance
from dlr
where dbo.latlngdistance(dlr.latitude, dlr.longitude,
(select lat from homeowner ho_identifier = 16),
(select lng from homeowner where ho_identifier = 16)) between 0 and 50
Order By SortDistance
我还有另一个查询,它返回所有客户50英里范围内的所有供应商(在此示例中我限制了客户数量,因为此查询的性能非常糟糕):
select ho.ho_identifier, ho.ho_firstname, ho.ho_lastname, ho.ho_email, dname1, dcity, dstate, dzip
from dlr
cross join homeowner ho
where dbo.latlngdistance(dlr.latitude, dlr.longitude,
(select lat from homeowner ho2 where ho.ho_identifier = ho2.ho_identifier),
(select lng from homeowner ho3 where ho.ho_identifier = ho3.ho_identifier)) between 0 and 50
and ho.ho_identifier in (16, 17, 18, 19, 20)
Order By ho.ho_identifier
所以我的问题是我如何获得(最多)半径50英里范围内最靠近所有客户的三家供应商?
答案 0 :(得分:0)
我会创建一个类似于此的定义的视图:
SELECT
ho.ho_identifier, dlr.dname1, --dlr.id would be even better, but you didnt give the name of the id column
dbo.latlngdistance(dlr.latitute, dlr.longtitude, ho.lat, ho.lng) AS distance
FROM dlr d
CROSS JOIN homeowner ho
鉴于此视图将被称为calculatedDistances,您可以找到最近的支持者,例如:
SELECT ho.ho_identifier, dlr.dname1
FROM homeowner ho
JOIN calculatedDistances dis
ON dis.ho_identifier = ho.ho_identifier
WHERE
NOT EXISTS(
SELECT 1
FROM calculatedDistances nearer
WHERE
nearer.distance < dis.distance
AND nearer.ho_identifier = ho.ho_identifier
)
找到最接近的三个会更棘手,可能会涉及一些严重的性能问题。你可以这样做:
SELECT
dis.ho_identifier, dis.dname1
FROM calculatedDistances dis
LEFT JOIN calculatedDistances nearer
ON nearer.ho_identifier = dis.ho_identifier
AND nearer.distance < dis.distance
GROUP BY dis.ho_identifier, dis.dname1
HAVING ISNULL(COUNT(1), 0) < 3
再次 - 如果遇到性能问题,您可能需要将calcutedDistance存储在其他表中。
如果我犯了任何错误,现在已经很晚了。如果是这样,请评论这个答案,我会尽力纠正自己。
答案 1 :(得分:0)
这是前同事建议的:
我想我会尝试将目标房主收集到一个临时表中以保存内容,然后使用SQL逐步逐步完成每一步。
比如(记住你我无法测试任何这个)
Select HO_Identifier, zip.lat, zip.lng INTO MyTempHO
From DBC_Homeowner
LEFT Join Zip on zip.zip = left(5,HO_Zip) AND Zip.ll = 'L' //I think there might also be a function to get lat/lng from zip....
WHERE <Your homeowner selection criteria>
这应该会给你一个较小的表来使用。检查所有Lat,Lng字段是否已填写,某些部分的拉链可能存在问题。当然是左(5只适用于美国,不适用于加拿大)
创建另一个表来保存结果,例如
CREATE TABLE MyResults (HO_Identifier int,DLR_Identifier int)
写一个循环来遍历每一行并找到前3个经销商,例如
//将所有这些作为一个语句运行
Declare @HO_Identifier int, @HO_Lat double, @HO_Lng double
Declare Cursor HO from select HO_Identifier , Lat, Lang from MyTempHO
OPEN HO
FETCH FROM HO Into @HO_Identifier, @HO_Lat, @HO_Lng
While @@INDEX = 0
BEGIN
Insert MyResults (@HO_Identifier, Dlr.dlr_Identifier) Select TOP 3 DLR_Identifier from dlr
where dbo.LAtLngDistance(@HO_Lat, @HO_Lng, dlr.lat, dlr.lng) < 100
AND <Your other dlr criteria>
AND dlr.lng between HO_Lng + <some negative amount to limit results> AND HO_Lng - <Same negative amount> //Note lng is negative!
ORDER BY dbo.LAtLngDistance(@HO_Lat, @HO_Lng, dlr.lat, dlr.lng)
FETCH NEXT FROM HO Into @HO_Identifier, @HO_Lat, @HO_Lng
END
CLOSE HO
DEALLOCATE HO