I have a query that takes too long and frequently times out. It's a proximity based zip code search table-value function. Is there anyway to index based on the query, so it doesn't have to recalculate all of these values every time? The postal code and zip code list combined is over a million rows.
Here is the table function.
Create FUNCTION [dbo].[ZipsInRadius] (@zipCode varchar(15),
@radius int, @unit char(1))
RETURNS @areaResults TABLE(
Zip varchar (30),
City varchar (255),
St varchar (20),
Lat decimal (16,12),
Long decimal (16,12))
BEGIN
DECLARE @iStartLat decimal(16, 12)
DECLARE @iStartLong decimal(16, 12)
SELECT
@iStartLat = CAST(Latitude AS decimal(16, 12)),
@iStartLong = CAST(Longitude AS decimal(16, 12))
FROM zip
WHERE zipcode LIKE @zipCode + '%'
SELECT
@iStartLat = CAST(Latitude AS decimal(16, 12)),
@iStartLong = CAST(Longitude AS decimal(16, 12))
FROM postalcode
WHERE postalcode LIKE @zipCode + '%'
DECLARE @latRange decimal(16, 12)
DECLARE @longRange decimal(16, 12)
IF (@unit = 'K') --Get distance in kilometers
BEGIN
SELECT @LatRange =
(CAST(@radius / ((6076.0 / 5280.0) * 60.0)
AS decimal(16, 12))) * 0.621371
SELECT @LongRange =
(@radius / (((cos(@iStartLat * pi() / 180.0) * 6076.0)
/ 5280.0) * 60)) * 0.621371
END
ELSE --Get distance in miles (the default)
BEGIN
SELECT @LatRange = CAST(@radius / ((6076.0 / 5280.0) * 60.0)
AS decimal(16, 12))
SELECT @LongRange =
@radius / (((cos(@iStartLat * pi() / 180.0) * 6076.0)
/ 5280.0) * 60)
END
DECLARE @lowLatitude decimal(16, 12)
DECLARE @highLatitude decimal(16, 12)
DECLARE @lowLongitude decimal (16, 12)
DECLARE @highLongitude decimal (16, 12)
SELECT @lowLatitude = @iStartLat - @latRange
SELECT @highLatitude = @iStartLat + @latRange
SELECT @lowLongitude = @iStartLong - @longRange
SELECT @highLongitude = @iStartLong + @longRange
INSERT INTO @areaResults (zip, city, st, lat, long)
SELECT ZIPcode, CITY, STate, LATitude, LONGitude
FROM Zip Z
WHERE Z.Latitude <= @highLatitude
AND Z.Latitude >= @lowLatitude
AND Z.Longitude >= @lowLongitude
AND Z.Longitude <= @highLongitude
INSERT INTO @areaResults (zip, city, st, lat, long)
SELECT postalcode, CITY, province, LATitude, LONGitude
FROM postalcode z
WHERE Z.Latitude <= @highLatitude
AND Z.Latitude >= @lowLatitude
AND Z.Longitude >= @lowLongitude
AND Z.Longitude <= @highLongitude
RETURN
END