我使用Postgresql 9.6
我有一个包含数据行的表。我们称之为TABLE1。 TABLE1有一个pkid列(一个串行主键)。
实际上,每行都是建筑物,分组操作基于建筑物是否相互接触(数据库是PostGIS扩展名)。 现在,我的问题是没有检测到两栋建筑物何时碰到其他建筑物,而是将这些建筑物记录在临时桌子中。
我使用SELECT子查询提取它们的子集(让它称之为子查询1),我需要根据某个标准对它们进行分组。 Subquery1返回一组包含两列的行,pkid_bat1和pkid_bat2,两个不同的TABLE1行的pkid关联在一起(基于使用PostGIS函数的JOIN)。
我举一个例子来说清楚:
我们说我有3栋建筑彼此接触:A,B和C. Subquery1将返回6行作为pkid对: A-B,B-A,A-C,C-A,B-C,C-B。
为了记录这三座建筑物是联系在一起的,我实际上只需要两对,例如:A-B和A-C。
所以我到目前为止所做的是:在subquery1之后,我已经嵌套了另一个SELECT子查询(subquery2),对于每个6行,返回第一列,两个pkid的min和第二列,两个pkid的最大值并添加了一个DISTINCT子句。 因此,6行A-B,B-A,A-C,C-A,B-C,C-B变为3行:A-B,A-C,B-C。
我仍然需要摆脱B-C行。
在subquery2之后,我还有另一个嵌套子查询(subquery3),它对子查询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
这有效:从A-B,A-C和B-C行开始,它只保留A-B和A-C,因为A永远不会出现在pkid_bat2中(这要归功于使用subquery2中的min和max函数)。 但这需要太多时间。
有没有其他方法可以解决这类问题(创建pkid集合)?
编辑: 整个代码在子查询2中有一个小的变化,以替换使用DISTINCT + min和max,更简单地使用'<'在WHERE子句中:
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
答案 0 :(得分:0)
即使很难,我确信你最终可以找到解决这个问题的SQL解决方案(最有可能使用分层查询),我认为使用过程逻辑来过滤多余的行要简单得多。
您的应用程序中的简单逻辑将比尝试复杂(且非常慢)的SQL更有效。
您只需要以简单有序的方式检索行。