Есть ли более эффективный способ вернуть запись максимального пространственного пересечения в SQL? - PullRequest
5 голосов
/ 15 марта 2019

У меня есть две таблицы в SQL.Первый - это полигоны проекта.Второй - это любая граница, которую я хочу применить к полигонам проекта на основе максимального пространственного пересечения.

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

Я сделал это с помощью запроса ниже.PrjID - это таблица проектов, а STATE - таблица состояний.Я хочу, чтобы возвращалось statename на основе максимального пересечения между каждой записью PrjID и записью STATE.

SELECT *
FROM
(SELECT a.PROJECT_DELIVERY_ID, b.statename, a.Shape.STIntersection(b.Shape).STArea() AS Area
    FROM PrjID a
        INNER JOIN STATE b
            ON a.Shape.STIntersects(b.Shape) = 1) as c
INNER JOIN
(SELECT a.PROJECT_DELIVERY_ID, MAX(a.Shape.STIntersection(b.Shape).STArea()) AS Area
    FROM PrjID a
        INNER JOIN STATE b
            ON a.Shape.STIntersects(b.Shape) = 1
    GROUP BY a.PROJECT_DELIVERY_ID) as d
ON c.PROJECT_DELIVERY_ID = d.PROJECT_DELIVERY_ID
    AND c.Area = d.Area

Мне кажется, что я выполняю один и тот же запрос дважды и присоединяюсь к ним.Есть ли более эффективный способ сделать это?

Спасибо

Ответы [ 2 ]

2 голосов
/ 15 марта 2019

если я правильно понял, вы хотите получить максимальный ряд области. Вы можете использовать ROW_NUMBER().

SELECT * FROM (
    SELECT a.PROJECT_DELIVERY_ID, b.statename, a.Shape.STIntersection(b.Shape).STArea() AS Area, 
        ROW_NUMBER() OVER(PARTITION BY a.PROJECT_DELIVERY_ID ORDER BY a.Shape.STIntersection(b.Shape).STArea() DESC) RN
        FROM PrjID a
            INNER JOIN STATE b
                ON a.Shape.STIntersects(b.Shape) = 1 ) AS T
WHERE RN = 1
1 голос
/ 15 марта 2019

Поскольку второе «табличное выражение» может быть построено из первого, вы можете использовать CTE (Common Table Expression), как в:

with
c as (
  SELECT
    a.PROJECT_DELIVERY_ID, 
    b.statename,
    a.Shape.STIntersection(b.Shape).STArea() AS Area
  FROM PrjID a
  INNER JOIN STATE b ON a.Shape.STIntersects(b.Shape) = 1
),
d as (
  select PROJECT_DELIVERY_ID, max(Area) AS Area
  from c
  group by PROJECT_DELIVERY_ID
)
select * 
from c
join d on c.PROJECT_DELIVERY_ID = d.PROJECT_DELIVERY_ID
    AND c.Area = d.Area

Здесь d вычисляется из c.Нет необходимости сканировать таблицу PrjID или STATE снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...