I have 2 tables:
tZipCodeNoCity with ZipCode and PointGeography
and MBLPosition with Latitude and Longitude
In this query I’m finding closest ZipCode to my positions. It’s “poor mans” geocoding 🙂
How do I write this query so I don’t have to do this SELECT TOP 1 inline?
It’s pretty slow with even 150 devices (like 20 seconds)
I had to include 150 mile radius into this subselect to get it faster
SELECT LastPositions.DeviceId, P.Description, P.Latitude, P.Longitude, P.Speed, P.DeviceTime,
(
SELECT TOP 1 ZC.ZipCode
FROM dbo.tZipCodeNoCity ZC
WHERE ZC.PointGeography.STDistance(geography::STPointFromText('POINT(' + CAST(P.Longitude AS VARCHAR(20)) + ' ' + CAST(P.Latitude AS VARCHAR(20)) + ')', 4326)) < 150 * 1609.344
ORDER BY ZC.PointGeography.STDistance(geography::STPointFromText('POINT(' + CAST(P.Longitude AS VARCHAR(20)) + ' ' + CAST(P.Latitude AS VARCHAR(20)) + ')', 4326))
)
FROM dbo.MBLPosition P
INNER JOIN
(
SELECT D.DeviceId, MAX(P.PositionKey) LastPositionKey
FROM dbo.MBLPosition P
INNER JOIN IDATTApplication.dbo.MBLDevice D ON P.DeviceKey = D.DeviceKey
GROUP BY D.DeviceId
) LastPositions ON P.PositionKey = LastPositions.LastPositionKey
In a project I worked on about 12 years ago, I ran a query along these lines to reduce the list of possibilities before doing the actual distance calculation:
From that subset, I calculate the actual distance between the two points and sort on it. You’ll have to adjust the “0.5” portion as appropriate to get a big enough box to be sure you’re going to get a hit.
And I would imagine that there’s a better way than
STPointFromTextto create your point object. Could you useSTPointFromWKB? Could you convert to thegeographytype once?See this page for an example of creating your point via
SET.