Дополнительные пункты с типом CTE и Geopgraphy - PullRequest
0 голосов
/ 06 ноября 2011

Я создаю запрос для сопоставления на основе расстояния людей, использующих почтовые индексы, используя тип данных Geography в SQL Server. У меня там 99%, но у меня две проблемы. На данный момент это поиск по почтовому индексу, городу и штату, но мне также нужно действительно сопоставить [u.username]. Я не могу получить правильный синтаксис, чтобы добавить «ИЛИ Имя пользователя LIKE @Name». Во-вторых, производительность невелика. Для 21 тестового пользователя со всего США запрос занимает 4 секунды.

Есть ли способ ускорить это и добавить дополнительные параметры поиска. У меня есть это до сих пор:

DECLARE @miles [float] = 10000;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '11204';

SELECT z.*,z.GeoLocation.STDistance(@myposition) AS Distance INTO #HASHTABLE FROM ZipCodes z
WHERE z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
ORDER BY Distance asc

;WITH Results_CTE AS (SELECT u.*,z.GeoLocation.STDistance(@myposition) AS Distance, ROW_NUMBER() OVER (ORDER BY z.GeoLocation.STDistance(@myposition)) AS RowNum
FROM Users u INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE u.PostCode in (SELECT Zip from #hashtable) OR u.City in (SELECT City from #hashtable) 
) SELECT * FROM Results_CTE WHERE RowNum > 0 
DROP TABLE #Hashtable

Ответы [ 2 ]

1 голос
/ 12 ноября 2011

Спасибо @cipx, но я обнаружил, что ваше предложение на самом деле вернуло дубликаты. После того, как я посмотрел на это свежим взглядом, у меня появился способ поиска по нескольким полям с помощью AND или OR.

DECLARE @miles [float] = 100;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '28790'; --OR city like 'brooklyn';--'11204';

SELECT z.*,z.GeoLocation.STDistance(@myposition) AS Distance INTO #HASHTABLE FROM ZipCodes z
WHERE z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
ORDER BY Distance asc

;WITH Results_CTE AS (SELECT u.*,z.GeoLocation.STDistance(@myposition) AS Distance, ROW_NUMBER() OVER (ORDER BY z.GeoLocation.STDistance(@myposition), userid) AS RowNum
FROM Users u INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE 
-- Using zip code and distance
-- u.PostCode in (SELECT Zip from #hashtable) 

-- using a link table to find users skilled in wrestling
-- OR UserID IN (SELECT UserID from UserSkills us INNER JOIN Skills s ON us.SkillID = s.SkillID WHERE s.Name LIKE 'wrestlin%') 

-- scalar properties of the UserProfiles table
-- DisplayName like 'johnny%'
) SELECT * FROM Results_CTE WHERE RowNum > 0 
DROP TABLE #Hashtable

Это дает мне возможность пейджинга и опроса более 300 пользователей по нескольким различным полям примерно за секунду, что не очень хорошо, но сейчас это приемлемо.

1 голос
/ 07 ноября 2011

есть ли у вас какие-либо объявленные индексы? Я бы отказался от временной таблицы и написал следующий запрос, а также добавил несколько индексов: для таблицы ZipCodes (пространственный индекс в столбце GeoLocation) и для таблицы пользователей (в столбцах City и Zip).

DECLARE @miles [float] = 10000;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '11204';

SELECT u.*,z.GeoLocation.STDistance(@myposition) as Distance from Users u
INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE
    z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
AND
    u.Username LIKE '%'+@Name+'%'

UNION

SELECT u.*,z.GeoLocation.STDistance(@myposition) as Distance from Users u
INNER JOIN ZipCodes z ON u.City = z.City
WHERE
    z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
AND
    u.Username LIKE '%'+@Name+'%'

ORDER BY
    z.GeoLocation.STDistance(@myposition)
...