获取多边形的子/父关系

时间:2019-04-07 16:23:04

标签: sql postgresql

我正在尝试使用data class A( val str: set<String> = emptySet() )从开放式街道地图数据库中提取父子关系,但是我在SQL方面表现特别糟糕。

简而言之,表ST_Contains(parent, child)看起来像这样:

planet_osm_polygon

我想提取父子关系,其中子是一行,多边形位于其父级内,并且admin_level尽可能低,但不等于其父级(可能很明显,只是在说)。

我到目前为止所做的事情

我设法编写了一个查询,该查询为我提供了每个区域的父级,但没有一个具有最低的admin_level父级-因此可以显示具有admin_level = 6的父级区域。我希望孩子与可能具有最低admin_level的父母一起出现,在这种情况下为4。

这是我失败的查询:

| osm_id | name      | admin_level | way            |
-------------------------------------------------
| 4667   | France    | 2           | {polygon data} |
| 4667   | Normandie | 4           | {polygon data} |
| 4667   | A place   | 6           | {polygon data} |
etc...

这是失败的示例结果:

SELECT
DISTINCT ON (childTable.osm_id)
childTable.admin_level AS child_level,
childTable.name AS child_name,
parentTable.name AS parent,
parentTable.admin_level AS parent_level

FROM planet_osm_polygon AS childTable
RIGHT JOIN planet_osm_polygon AS parentTable
ON ST_Contains(parentTable.way, childTable.way)
AND childTable.admin_level > parentTable.admin_level;

这就是我想要的样子:

| Child level | Child name | Parent name | Parent level |
---------------------------------------------------------
| 6           | Some place | France      | 2            |
| 4           | Another    | France      | 2            |
| 6           | And again  | France      | 2            |
etc...

注意:我已删除了与admin_level 1、3、5有关的所有数据,因此我只有admin_level 2、4和6的多边形,但是对于其他情况,这可能有所不同,因此您不认为这是可以对admin_levels

进行硬编码

1 个答案:

答案 0 :(得分:1)

如果我的问题没错,您可以使用row_number()窗口函数为一个孩子的每个父母分配一个数字,该数字对于最低管理员级别的数字是1并对其进行过滤

SELECT child_level,
       child_name,
       parent_name,
       parent_level
       FROM (SELECT childtable.admin_level child_level,
                    childtable.name child_name,
                    parenttable.name parent_name,
                    parenttable.admin_level parent_level
                    row_number() OVER (PARTITION BY childtable.name
                                       ORDER BY parenttable.admin_level) rn
                    FROM planet_osm_polygon childtable
                         RIGHT JOIN planet_osm_polygon parenttable
                                    ON st_contains(parenttable.way, childtable.way)
                                       AND childtable.admin_level > parenttable.admin_level) x
       WHERE rn = 1;

如果每个多边形都有唯一的ID <id>,则应将PARTITION BY childtable.name替换为PARTITION BY childtable.<id>或检查名称是否唯一。否则,在其他位置共享名称的地方可能会得到错误的结果。

我也不确定您的正确联接是否应为其他联接。如果要向所有父母显示,即使没有适合他们的孩子,也请保持正确的联系。如果要显示所有孩子(也包括孤儿),请将其左连接。如果只想显示有父母的孩子和有孩子的父母使用内部联接。