如何将“精简”PostgreSQL行扩展为单独的列?

时间:2014-06-27 04:34:56

标签: sql postgresql

我有一个返回表的函数。

如果您运行SELECT * FROM some_function(12345),结果为:

object_id | name
----------------
    12345 | "B"

如果您运行SELECT some_function(12345),结果为:

some_function
-------------
(12345,"B")

问题是我想要原始表单(以便我可以访问单个列值),但是some_function()的参数来自表中的列。我可以执行SELECT some_function(thing_id) FROM things,但这会返回:

some_function
-------------
(12345,"B")
(12346,"C")
(12347,"D")

而我想要的是:

object_id | name
----------------
    12345 | "B"
    12346 | "C"
    12347 | "D"

那么一个人怎么可能不会"或"扩展"这样一个浓缩的行?

2 个答案:

答案 0 :(得分:21)

9.3及以上:横向查询

在PostgreSQL 9.3或更新版本中使用隐式横向查询:

SELECT f.* FROM things t, some_function(t.thing_id) f;

首选此配方所有新查询。以上是标准配方

它也适用于RETURNS TABLERETURNS SETOF RECORD的函数以及RETURNS RECORD的out-params的函数。

它的简写:

SELECT f.*
FROM things t
CROSS JOIN LATERAL some_function(t.thing_id) f;

9.3之前:通配符扩展(小心)

之前的版本会导致some_function的多重评估,如果some_function返回一个,那么是否正常工作:不使用此:< / p>

SELECT (some_function(thing_id)).* FROM things;

以前的版本,避免使用第二层间接对some_function进行多重评估。只有在你必须支持相当旧的PostgreSQL版本时才使用它。

SELECT (f).*
FROM (
  SELECT some_function(thing_id) f
  FROM things
) sub(f);

演示:

设定:

CREATE FUNCTION some_function(i IN integer, x OUT integer, y OUT text, z OUT text) RETURNS record LANGUAGE plpgsql AS $$
BEGIN
  RAISE NOTICE 'evaluated with %',i;
  x := i;
  y := i::text;
  z := 'dummy';
  RETURN;
END;
$$;

create table things(thing_id integer);
insert into things(thing_id) values (1),(2),(3);

试运行:

demo=>     SELECT f.* FROM things t, some_function(t.thing_id) f;
NOTICE:  evaluated with 1
NOTICE:  evaluated with 2
NOTICE:  evaluated with 3
 x | y |   z   
---+---+-------
 1 | 1 | dummy
 2 | 2 | dummy
 3 | 3 | dummy
(3 rows)

demo=>     SELECT (some_function(thing_id)).* FROM things;
NOTICE:  evaluated with 1
NOTICE:  evaluated with 1
NOTICE:  evaluated with 1
NOTICE:  evaluated with 2
NOTICE:  evaluated with 2
NOTICE:  evaluated with 2
NOTICE:  evaluated with 3
NOTICE:  evaluated with 3
NOTICE:  evaluated with 3
 x | y |   z   
---+---+-------
 1 | 1 | dummy
 2 | 2 | dummy
 3 | 3 | dummy
(3 rows)

demo=>  SELECT (f).*
    FROM (
      SELECT some_function(thing_id) f
      FROM things
    ) sub(f);
NOTICE:  evaluated with 1
NOTICE:  evaluated with 2
NOTICE:  evaluated with 3
 x | y |   z   
---+---+-------
 1 | 1 | dummy
 2 | 2 | dummy
 3 | 3 | dummy
(3 rows)

答案 1 :(得分:-1)

SELECT * FROM (SELECT some_function(thing_id) FROM things) x;

子选择SELECT some_function(thing_id) FROM things为找到的每条记录返回一行。外部选择&#34;解压缩&#34;该行分为不同的列。