【问题标题】:How to filter the max value and write to row?如何过滤最大值并写入行?
【发布时间】:2015-08-12 11:43:31
【问题描述】:

Postgres 9.3.5,PostGIS 2.1.4。

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

我想知道每个polygon 中有多少points。每个多边形将有 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. 如果最大值可能相同,将如何处理?

【问题讨论】:

  • 第二个问题应该是你自己回答的,你希望这些人怎么处理?
  • @JakubKania 我想知道它是否会引发错误或让我注意到发生了什么。就是这样。
  • 这是 groupwise max 的经典案例(一旦你放弃了 ST_Within 和插入的性能),所以你应该决定是否要出错。
  • @JakubKania “一旦你放弃 ST_Within 和插入的性能”是什么意思?

标签: sql postgresql postgis greatest-n-per-group groupwise-maximum


【解决方案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 个点),这应该大大更快(希望更好地利用@987654328 上的索引@):

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

在此处使用window function rank()(不是row_number()!)。我们可以在单个SELECT 中获得计数或积分计数的排名。考虑事件的顺序:

【讨论】:

    猜你喜欢
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    相关资源
    最近更新 更多