一直以来,我对这个问题都有一个变种,不记得怎么解决,只记得“oop很简单,但是怎么解决呢?”... 也许有一些模式和最好的方法来处理每个模式。让我们看看主要的一个,例如unnest()ts_stat()
首先,好的例子,没有问题,因为unnest()只返回一列:

SELECT * FROM unnest(array[1,2,3]) t(id); -- is ok, the int columns there!
SELECT unnest(array[1,2,3]) t(id); -- is ok, the int columns

WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, unnest(array[4,id]) as x
 FROM t;  -- more complex, but ok!

现在是一个返回已定义记录集的函数,
SELECT * FROM ts_stat('SELECT kx FROM terms where id=2') -- GOOD
-- show all word|ndoc|nentry columns

SELECT ts_stat('SELECT kx FROM terms where id=2') as x -- BAD
-- because lost columns, show only "x" column... but works

-- NOTE: you can imagine any other function, as json_each(), etc.

看到好/坏的考虑。。。所以,这就是问题所在:一组记录有多个tham一列。在最简单(unnest以上)的情况下,解决方案是在“FROM side”中用作表;但是,当记录有多个字段时,就会出现问题。
--MAIN EXAMPLE FOR THE DISCUSSION:
WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, ts_stat('SELECT kx FROM terms where id='||id) as x
 FROM t;  -- BAD, but works...

现在,在这个主要的例子中,不可能在“FROM side”中使用ts_stat(),因此,描述模式:返回一个表或一组记录的函数,在我们需要列的查询中,但函数不能在“FROM side”中。
问题:这个模式的通用(也是最优雅的)解决方案是什么?如何(语法模式)显示列?
注意:另一个问题是,如果你不完全记住解决方案的语法,你会尝试不起作用的东西。。。在这种情况下会出现错误:
WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, x.word, x.ndoc, x.nentry
 FROM (
      SELECT t.nsid,
             ts_stat('SELECT kx FROM terms where id='||id) as x
      FROM t
  ) s;

SQL语法分析器错误(PostgreSQL 9.5):from子句中没有表“x”。

最佳答案

您不应该在SELECT列表中使用set-returning-function (SRF)。主要示例应该用隐式LATERAL JOIN编写:

SELECT v.id, x.*
FROM (VALUES (1),(2),(3)) v(id)
JOIN ts_stat('SELECT kx FROM terms where id=' || v.id) x ON true;

这里的lateral join是隐式的,因为SRF可以引用在其FROM子句之前指定的关系中的列,而不使用关键字LATERAL。在上面的例子中,SRFts_stat()对列和关系进行了横向引用。您也可以通过子查询这样做,但是您必须显式地使用关键字v(id)
请注意,虽然可以在选择列表中使用SRF,但不鼓励使用它。您提供了一个有趣的LATERAL示例,因为还有一个重载变量unnest(anyarray)(即,在一个调用中不使用多个数组),当在选择列表中使用时,该变量将引发错误;in只能用作行源。不应该在选择列表中使用srf的原因是,当使用多个srf(每个srf生成不同数量的行)时,没有明显的解决方案。

关于postgresql - 从返回表(或记录集)的函数中检索列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36065650/

10-11 04:41