postgresql - 为什么 PostgreSQL 以错误的方式组合系列?

标签 postgresql combinations postgis generate-series

我得到了组合 generate_series 的一些奇怪行为。在我尝试用网格填充的 2 个不同的多边形中,一个网格要少得多:

enter image description here

查询是这样的:

SELECT
    osm_id ,
        generate_series(floor(st_xmin(way))::int, ceiling(st_xmax(way))::int, 150) x,
        generate_series(floor(st_ymin(way))::int, ceiling(st_ymax(way))::int, 150) y 
from osm_polygon
order by osm_id, x, y;

我尝试追踪问题,只是输入了最小/最大坐标。从最小值/最大值生成系列创建正确数量的值:分别为 9 行和 12 行。

  => select generate_series(9237195, 9238873, 150) x;
      x    
  ---------
   9237195
   9237345
   9237495
   9237645
   9237795
   9237945
   9238095
   9238245
   9238395
   9238545
   9238695
   9238845
  (12 rows)

  => select generate_series(7371701, 7372922, 150) y order by y;
      y    
  ---------
   7371701
   7371851
   7372001
   7372151
   7372301
   7372451
   7372601
   7372751
   7372901
  (9 rows)

它们加起来应该有 108 行,对吧?不,只有 36 行:

=> select generate_series(9237195, 9238873, 150) x, generate_series(7371701, 7372922, 150) y order by x, y;
      x    |    y    
  ---------+---------
   9237195 | 7371701
   9237195 | 7372151
   9237195 | 7372601
   9237345 | 7371851
   9237345 | 7372301
   9237345 | 7372751
   9237495 | 7372001
   9237495 | 7372451
   9237495 | 7372901
   9237645 | 7371701
   9237645 | 7372151
   9237645 | 7372601
   9237795 | 7371851
   9237795 | 7372301
   9237795 | 7372751
   9237945 | 7372001
   9237945 | 7372451
   9237945 | 7372901
   9238095 | 7371701
   9238095 | 7372151
   9238095 | 7372601
   9238245 | 7371851
   9238245 | 7372301
   9238245 | 7372751
   9238395 | 7372001
   9238395 | 7372451
   9238395 | 7372901
   9238545 | 7371701
   9238545 | 7372151
   9238545 | 7372601
   9238695 | 7371851
   9238695 | 7372301
   9238695 | 7372751
   9238845 | 7372001
   9238845 | 7372451
   9238845 | 7372901
(36 rows)

蛮力实际上在这里起作用:

with a as (select generate_series(9237195, 9238873, 150) x),
    b as (select generate_series(7371701, 7372922, 150) y)
select x, y from a, b;

生成 108 行。很好,只是查询变得更复杂。

为什么会这样?

Postgres 版本是 9.1

最佳答案

这是在 SELECT 列表中调用时如何执行多个设置返回函数的怪癖。您希望结果是两者的叉积,但事实并非如此。它实际上是两者行数的最小公倍数。

参见:

比较:

test=>     SELECT generate_series(1,3) aval, generate_series(1,4) bval;
 aval | bval 
------+------
    1 |    1
    2 |    2
    3 |    3
    1 |    4
    2 |    1
    3 |    2
    1 |    3
    2 |    4
    3 |    1
    1 |    2
    2 |    3
    3 |    4
(12 rows)

test=>     SELECT generate_series(1,3) aval, generate_series(1,3) bval;
 aval | bval 
------+------
    1 |    1
    2 |    2
    3 |    3
(3 rows)

因此,在 PostgreSQL 9.2 及更高版本上,您应该使用 LATERAL 查询,其中您在 FROM 子句中调用集合返回函数:

test=>     SELECT aval, bval FROM generate_series(1,3) aval CROSS JOIN LATERAL generate_series(1,3) bval;
 aval | bval 
------+------
    1 |    1
    1 |    2
    1 |    3
    2 |    1
    2 |    2
    2 |    3
    3 |    1
    3 |    2
    3 |    3
(9 rows)

test=>     SELECT aval, bval FROM generate_series(1,3) aval CROSS JOIN LATERAL generate_series(1,4) bval;
 aval | bval 
------+------
    1 |    1
    1 |    2
    1 |    3
    1 |    4
    2 |    1
    2 |    2
    2 |    3
    2 |    4
    3 |    1
    3 |    2
    3 |    3
    3 |    4
(12 rows)

在旧版本上,您可以使用 FROM 中的子查询来避免在 SELECT 术语中有多个 SRF:

test=> SELECT generate_series(1,3) aval, bval FROM (SELECT generate_series(1,4)) AS x(bval);
 aval | bval 
------+------
    1 |    1
    2 |    1
    3 |    1
    1 |    2
    2 |    2
    3 |    2
    1 |    3
    2 |    3
    3 |    3
    1 |    4
    2 |    4
    3 |    4
(12 rows)

关于postgresql - 为什么 PostgreSQL 以错误的方式组合系列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31202501/

相关文章:

postgresql - 请求了未知的数据库类型 tsvector

sql - 对于我的智力来说,太多的 order by、max、子查询

javascript - 如何打印 DOM 对象的选择器

postgresql - 如何使用 PostgreSQL 中的字段创建多边形?

postgresql - 将两个数据字段插入到具有相同投影的 PostGis 中的单个数据字段中

sql - WHERE 与 PARTITION BY postgres 一起使用

sql - 用于多列比较的索引扫描 - 非统一索引列排序

python - Python 扩展模块的 C 代码中的 "if item in list/set' 相当于什么?

r - 如何从 2 个或更多矩阵的所有可能组合创建矩阵?

postgresql - 每行的 st_intersect 计数结果