单个选择列表中的SQL多个UNNEST

use*_*878 5 sql postgresql unnest set-returning-functions

我正在实现一个Query系统.我实现了不需要的功能.现在用户询问在单个select语句中使用多个unfst.我使用PostgreSQL作为指南,因为大多数用户在我们的查询系统之前使用它.

PostgreSQL有这样奇怪的行为:

postgres=# select unnest(array[1,2]), unnest(array[1,2]);
 unnest | unnest
--------+--------
      1 |      1
      2 |      2
(2 rows)

postgres=# select unnest(array[1,2]), unnest(array[1,2,3]);
 unnest | unnest
--------+--------
      1 |      1
      2 |      2
      1 |      3
      2 |      1
      1 |      2
      2 |      3
(6 rows)
Run Code Online (Sandbox Code Playgroud)

我的实现总是生成笛卡尔积.我想知道,这背后的正确逻辑是什么?PostgreSQL正在做正确的事还是只是一个bug?我没有在ANSI文档或PostgreSQL文档中找到明确的描述.

Cra*_*ger 7

这不是关于不必要的,而是关于PostgreSQL对SELECT列表中多个集合返回函数的非常奇怪的处理.集合返回函数SELECT不是ANSI SQL标准的一部分.

你会发现LATERAL查询的行为更加理智,这应该优先于FROM尽可能使用set-returns函数:

select a, b FROM unnest(array[1,2]) a, LATERAL unnest(array[1,2,3]) b;
Run Code Online (Sandbox Code Playgroud)

例如

regress=> select a, b FROM unnest(array[1,2]) a, LATERAL unnest(array[1,2,3]) b;
 a | b 
---+---
 1 | 1
 1 | 2
 1 | 3
 2 | 1
 2 | 2
 2 | 3
(6 rows)
Run Code Online (Sandbox Code Playgroud)

我仍然使用多个set-returns函数的唯一一次SELECT是当我想要从返回相同行数的函数中配对值时.对此的需求将在9.4中消失,具有多论证unnest并且支持WITH ORDINALITY.

  • 请注意,**奇怪的行为在 Postgres 10** 结束(就像 Craig 预测的那样)。请参阅:/sf/answers/2790537081/ (2认同)