0

Postgres 9.3.5,PostGIS 2.1.4。

我在数据库中有两个表(polygonspoints)。

points我想知道每个中有多少polygon。每个多边形将有 0 个点或超过 200000 个点。小问题如下。

我的point表如下所示:

x    y    lan
10  11    en
10  11    fr
10  11    en
10  11    es
10  11    en
- #just for demonstration/clarification purposes
13  14    fr
13  14    fr
13  14    es
-
15  16    ar
15  16    ar
15  16    ps

我不想简单地计算每个多边形的点数。lan我想知道每个多边形中最常出现的是什么。因此,假设每个-点都表明这些点落入一个新的多边形中,我的结果将如下所示:

Polygon桌子:

polygon    Count   lan
1          3       en
2          2       fr
3          2       ar

这是我到目前为止得到的。

SELECT count(*), count.language AS language, hexagons.gid AS hexagonsWhere 
  FROM hexagonslan AS hexagons, 
       points_count AS france 
 WHERE ST_Within(count.geom, hexagons.geom) 
 GROUP BY language, hexagonsWhere 
 ORDER BY hexagons DESC;

它给了我以下信息:

Polygon    Count     language
1          3         en
1          1         fr
1          1         es
2          2         fr
2          1         es
3          2         ar
3          1         ps

有两件事尚不清楚。

  1. 如何只获得最大值?
  2. 如果最大值可能相同,将如何处理?
4

1 回答 1

1

回答 1。

要获得最常用的语言及其每个多边形的计数,您可以使用一个简单的DISTINCT ON查询:

SELECT DISTINCT ON (h.gid)
       h.gid AS polygon, count(c.geom) AS ct, c.language
FROM   hexagonslan h
LEFT   JOIN points_count c ON ST_Within(c.geom, h.geom)
GROUP  BY h.gid, c.language
ORDER  BY h.gid, count(c.geom) DESC, c.language;  -- language name is tiebreaker

但是对于您描述的数据分布(每个多边形最多 200.000 个点),这应该会更快(希望更好地利用 上的索引c.geom

SELECT h.gid AS polygon, c.ct, c.language
FROM   hexagonslan h
LEFT   JOIN LATERAL (
   SELECT c.language, count(*) AS ct
   FROM   points_count c
   WHERE  ST_Within(c.geom, h.geom) 
   GROUP  BY 1
   ORDER  BY 2 DESC, 1  -- again, language name is tiebreaker
   LIMIT  1
   ) c ON true
ORDER  BY 1;

LEFT JOIN LATERAL .. ON true保留不包含任何点的多边形。

cases where there are by any chance the max values identical中,在示例中通过添加的ORDER BY项目选择了按字母顺序排列的第一种语言。如果您希望所有碰巧共享最大数量的语言,您必须做更多:

回答2。

SELECT h.gid AS polygon, c.ct, c.language
FROM   hexagonslan h
LEFT   JOIN LATERAL (
   SELECT c.language, count(*) AS ct
        , rank() OVER (ORDER BY count(*) DESC) AS rnk
   FROM   points_count c
   WHERE  ST_Within(c.geom, h.geom) 
   GROUP  BY 1
   ) c ON c.rnk = 1
ORDER  BY 1, 3  -- language only as additional sort critieria

在这里使用窗口函数rank(),(不是row_number()!)。我们可以在单个 中获得计数或积分以及SELECT计数的排名。考虑事件的顺序:

于 2015-05-30T00:23:03.827 回答