所有时间我都有这个问题的变体,而不记得如何解决方法,只有" 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!
现在是一个返回已定义 SETOF RECORD 的函数,
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.
请参阅GOOD / BAD注意事项......所以,这是问题:一个SETOF RECORD,其中包含更多的一列。在最简单的(unnest
以上)情况下,解决方案是在" FROM侧"中使用,作为表格;但是,当RECORD有多个字段时,就会出现问题。
--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侧"中使用ts_stat()
,因此,表征模式:一个函数在我们需要列的查询中返回TABLE或SETOF RECORD,但该函数不能在" FROM侧" 。
问题:这个模式的通用(和最优雅)解决方案是什么?如何(语法模式)显示列?
注意:另一个问题是,如果你不记得确切的解决方案的语法,你会尝试不起作用的东西......在这种情况下是一个错误:
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 PARSER ERROR(PostgreSQL 9.5):没有表" x"在FROM子句中。
答案 0 :(得分:1)
您应该从不在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
。在上面的示例中,SRF ts_stat()
对列和关系v(id)
进行横向引用。您也可以使用例如子查询但您必须明确使用关键字LATERAL
。
请注意,虽然您可以在选择列表中使用SRF,但不建议使用它。您提供了unnest(anyarray)
的示例,这是有趣的,因为还有重载的变体unnest(anyarray, ...)
(即一次调用中不需要多个数组),当在选择列表中使用时会抛出错误; in只能用作行源。你不应该在选择列表中使用SRF的原因是当使用多个SRF时,没有明显的解决方案,每个SRF产生不同数量的行。