Как я могу сделать это «для каждого» кода в Sql Server 2008 без использования курсоров? - PullRequest
1 голос
/ 17 сентября 2010

Я хотел бы сделать следующий псевдо-код в Sql без использования CURSOR, если это возможно.

for each zipcode
{
    -- What city is this zipcode in? A zipcode can be in multiple cities, 
    -- but one city area is always way greater that the others.
    -- Eg. 90210 is 96% in the city of Beverly Hills. 
    -- The remaining 4% is that it s in some other fringe cties .. 
    --but only just (some mismatch mapping errors).

    ** grab the city largest shape area which this zip is a part of **
}

Теперь у меня есть немного SQL, чтобы помочь нам.

-- All zipcodes and each boundary/shapefile.
SELECT ZipCodeId, Boundary FROM ZipCodes -- Boundary is a GEOGRAPHY field type.

To determine if a zipcode boundary is in a city....
SELECT CityId, CityName, 
    City.Boundary.Intersection(@someZipCodeBoundary).STArea() AS Area
FROM Cities
WHERE City.Boundary.Intersects(@someZipCodeBoundary) = 1

и чтобы получить площадь пересечения (потому что мы хотим самую высокую площадь пересечения ... т.е.

ПРИМЕЧАНИЕ: Intersects и Intersection - это два разных метода Sql.

Так ... кто-нибудь может мне помочь? Я сосу на все это SET материал: (

Ответы [ 4 ]

0 голосов
/ 17 сентября 2010

Хорошо - понял;) Хитрость была в том, чтобы использовать PARTITION BY.@ In Sane дала мне идею, когда я поняла, что сделала что-то похожее, раньше:)

Итак ... мы идем ..

SELECT 
    a.CityId, a.Name, b.ZipCodeId, b.Code, a.Boundary.STIntersection(b.Boundary).STArea() AS Area, 
    RANK() OVER (PARTITION BY b.ZipCodeId ORDER BY a.Boundary.STIntersection(b.Boundary).STArea() DESC) AS Area_Rank
FROM 
    Cities a
    INNER JOIN ZipCodes b on a.Boundary.STIntersects(b.Boundary) = 1
    where b.Code = 12010 OR b.Code = 90210


CityId      Name                                                                                                 ZipCodeId   Code                 Area                   Area_Rank
----------- ---------------------------------------------------------------------------------------------------- ----------- -------------------- ---------------------- --------------------
2166        Los Angeles                                                                                          9331        90210                13235413.8430175       1
1686        Beverly Hills                                                                                        9331        90210                10413397.1372613       2
2635        West Hollywood                                                                                       9331        90210                0                      3
14570       Amsterdam                                                                                            29779       12010                15369521.9602067       1
14921       Hagaman                                                                                              29779       12010                1394562.70390667       2
14856       Fort Johnson                                                                                         29779       12010                211058.884834718       3
14651       Broadalbin                                                                                           29779       12010                0                      4

(7 row(s) affected)

Итак, в этом отфильтрованном примере (Filteredпо ZipCode 12010 или 90210), мы можем видеть, что этот почтовый индекс существует в 4 разных городах / поселках.Каждый почтовый индекс может иметь от 1 до многих результатов, которые затем упорядочиваются по значению Area ..., но ключевым здесь является ключевое слово PARTITION, которое выполняет это упорядочение по группам или разделам ZipCode.Очень забавно :) Заметьте, как почтовый индекс 90210 имеет свои собственные результаты ранга?то же самое с 12010?

Далее мы сделаем этот подзапрос и просто захватим весь ранг == 1:)

SELECT CityId, Name, ZipCodeId, Code, Area_Rank
FROM (
SELECT 
    a.CityId, a.Name, b.ZipCodeId, b.Code, a.Boundary.STIntersection(b.Boundary).STArea() AS Area, 
    RANK() OVER (PARTITION BY b.ZipCodeId ORDER BY a.Boundary.STIntersection(b.Boundary).STArea() DESC) AS Area_Rank
FROM 
    Cities a
    INNER JOIN ZipCodes b on a.Boundary.STIntersects(b.Boundary) = 1
    where b.Code = 12010 OR b.Code = 90210
) subQuery
WHERE Area_Rank = 1


CityId      Name                                                                                                 ZipCodeId   Code                 Area_Rank
----------- ---------------------------------------------------------------------------------------------------- ----------- -------------------- --------------------
14570       Amsterdam                                                                                            29779       12010                1
2166        Los Angeles                                                                                          9331        90210                1

(2 row(s) affected)

Сладкий как конфетка:)

СторонаПримечание. Это также показывает, что мой Лос-Анджелес городской шейп-файл / граница поврежден, поскольку он слишком сильно пересекает почтовый индекс 90210 (что я визуально подтвердил: P)

alt text

0 голосов
/ 17 сентября 2010

Я должен сказать, что я понятия не имею о том, что такое Пересечение / Пересечения или что они делают, и я должен уточнить, что я не понимаю этот синтаксис ниже Boundary.Intersection(@someZipCodeBoundary). либо

Предполагая, что этот запросyours возвращает все города, которые пересекаются с указанным zipcodeBoundary, а Area - это их площадь пересечения ,

SELECT 
    CityId, 
    CityName, 
    City.Boundary.Intersection(@someZipCodeBoundary).STArea() AS Area 
FROM 
    Cities 
WHERE 
    City.Boundary.Intersects(@someZipCodeBoundary) = 1 

Насколько я понимаю, то, что драхенштерн предлагает выше, касается использования MAX:

SELECT 
    CityId, 
    MAX(City.Boundary.Intersection(@someZipCodeBoundary).STArea()) AS Area
FROM 
    Cities 
WHERE 
    City.Boundary.Intersects(@someZipCodeBoundary) = 1 
GROUP BY CityId

Это должно дать вам CITYID, который имеет МАКСИМАЛЬНУЮ зону пересечения.

0 голосов
/ 17 сентября 2010

Попробуйте другой подход. Найдите где-нибудь статистику переписи и отфильтруйте города с максимальным населением, сгруппированным по тому же почтовому индексу.

Вот так Газетир , например.

0 голосов
/ 17 сентября 2010

Работает ли Max для этого?

...