一直以来,我对这个问题都有一个变种,不记得怎么解决,只记得“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/