我使用Postgresql 9.6
我有一张列有数据的表格。我们称之为表1。表1有一个pkid列(一个串行主键)。
实际上,每一行都是一个建筑物,分组操作是基于建筑物是否相互接触(数据库是PostGIS扩展)。
现在,我的问题不是探测到两栋楼之间的接触,而是在一张临时桌子上记录下这对。
我使用SELECT子查询(我们称之为subquery1)提取它们的一个子集,并需要根据特定条件对它们进行分组。
Subquery1返回一组行,其中有两列pkid_bat1和pkid_bat2,这两列是表1的两个不同行的pkid,它们关联在一起(基于使用PostGIS函数的连接)。
我举个例子来说明:
假设我有三座互相接触的建筑物:A、B和C。
子查询1将返回6行作为pkid对:
A-B,B-A,A-C,C-A,B-C,C-B。
为了记录这三座建筑是连在一起的,我实际上只需要两对,比如:A-B和A-C。
所以到目前为止,我所做的是:在subquery1之后,我嵌套了另一个SELECT子查询(subquery2),对于6行中的每一行,它作为第一列返回两个pkid的最小值,作为第二列返回两个pkid的最大值,并添加了一个不同的子句。
因此,6行A-B、B-A、A-C、C-A、B-C、C-B变成3行:A-B、A-C、B-C。
我还是要把B-C排去掉。
在子查询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
工作原理:从A-B、A-C和B-C行来看,它只保留A-B和A-C,因为A不在pkid-bat2中(由于在子查询2中使用了min和max函数)。
但这需要太多时间。
有没有其他方法来处理这种问题(创建pkid集)?
编辑:
整个代码在subquery2中有一个小的变化,用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
最佳答案
即使很难,我相信您最终可以找到解决此问题的纯SQL解决方案(很可能使用分层查询),我认为使用过程逻辑过滤多余的行要简单得多。
应用程序中的一个简单逻辑将比尝试复杂(而且非常慢)的SQL更有效。
您只需要以简单有序的方式检索行。