Postgresql-Postgis: группировка пар идентификаторов - PullRequest
0 голосов
/ 31 мая 2018

Я использую Postgresql 9,6

У меня есть таблица со строками данных.Давайте назовем это TABLE1.ТАБЛИЦА 1 имеет столбец pkid (серийный первичный ключ).

Фактически каждая строка является зданием, и операция группировки основана на том, касаются ли здания друг друга или нет (БД с расширением PostGIS).Теперь моя проблема не в том, чтобы определить, когда два здания касаются другого, а в том, чтобы записать пары во временную таблицу.

Я извлекаю их подмножество, используя подзапрос SELECT (давайте назовем его subquery1), иМне нужно сгруппировать их по определенным критериям.Подзапрос1 возвращает набор строк с двумя столбцами, pkid_bat1 и pkid_bat2, pkid 2 разных строк TABLE1, которые связаны вместе (на основе JOIN, использующего функцию PostGIS).

Я возьму примерЧтобы прояснить ситуацию:

Допустим, у меня есть 3 здания, которые касаются друг друга: A, B и C. Подзапрос1 вернет 6 строк в виде пар pkid: AB, BA, AC, CA, BC, CB.

Чтобы записать, что эти 3 здания связаны друг с другом, мне фактически нужны только 2 пары, такие как: AB и AC.

Итак, что я сделал до сих пор: после подзапроса1 у меня естьвложил другой подзапрос SELECT (подзапрос2), который для каждой из 6 строк возвращает в качестве первого столбца минимум двух pkid и в качестве 2-го столбца максимум двух pkid, и добавил предложение DISTINCT.Таким образом, 6 рядов AB, BA, AC, CA, BC, CB становятся 3 рядами: AB, AC, BC.

Мне все еще нужно избавиться от ряда BC.

Послеподзапрос2, у меня есть еще один вложенный подзапрос (подзапрос3), который самостоятельно объединяет результаты подзапроса2:

SELECT mpb1.pkid_bat1 , mpb1.pkid_bat2
FROM resultsSubQuery2 AS mpb1
LEFT JOIN resultsSubQuery2 AS mpb2
ON mpb1.pkid_bat1 = mpb2.pkid_bat2
WHERE mpb2.pkid_bat2 IS NULL

Это работает: из строк AB, AC и BC он будет содержать только AB иAC, потому что A никогда не находится среди pkid_bat2 (благодаря использованию функций min и max в подзапросе2).Но это занимает слишком много времени.

Есть ли другой способ решения этой проблемы (создание наборов pkid)?


Редактировать: Весьв коде есть небольшое изменение в подзапросе 2, чтобы заменить использование DISTINCT + min и max более простым использованием «<» в предложении WHERE: </p>

WITH isolatedPonctualBuildings AS
(   
    SELECT DISTINCT ON (bat.pkid)
        bat.pkid, bat.pkid_emprise, bat.origine , bat.origine_id, bat.geom  
        FROM Temp_batiments_sites AS bat
        LEFT JOIN Temp_recoupements_bâtiments AS recoup
            ON bat.pkid = recoup.pkid_batiment2
        WHERE bat.type_geometry = 'Point'
        AND recoup.pkid IS NULL 
), 
matchedPonctualBuildings AS
( 
    SELECT 
        bat1.pkid AS pkid_bat1, 
        bat2.pkid AS pkid_bat2 
        FROM isolatedPonctualBuildings AS bat1
        JOIN isolatedPonctualBuildings AS bat2
            ON bat1.pkid_emprise = bat2.pkid_emprise 
            AND ST_Intersects (bat1.geom , bat2.geom) 
            AND ( bat1.origine != bat2.origine OR bat1.origine_id != bat2.origine_id )
        WHERE bat1.pkid < bat2.pkid 
)
    SELECT
        mpb1.pkid_bat1 , mpb1.pkid_bat2
        FROM matchedPonctualBuildings AS mpb1
        LEFT JOIN matchedPonctualBuildings AS mpb2
            ON mpb1.pkid_bat1 = mpb2.pkid_bat2
        WHERE mpb2.pkid_bat2 IS NULL

1 Ответ

0 голосов
/ 31 мая 2018

Даже несмотря на то, что я уверен, что в конечном итоге вы сможете найти решение этой проблемы только для SQL (скорее всего, с использованием иерархических запросов), я думаю, что гораздо проще использовать процедурную логику для фильтрации лишних строк.

Простая логика в вашем приложении будет намного эффективнее, чем использование сложного (и очень медленного) SQL.

Вам просто нужно получить строки простым упорядоченным способом.

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