PostgreSQL:从返回复合类型的函数中选择

时间:2010-11-26 11:12:12

标签: sql postgresql composite

如何在SELECT中包含一个返回复合类型的函数?
我有复合类型:

CREATE TYPE "public"."dm_nameid" AS (
  "id" "public"."dm_int",
  "name" "public"."dm_str"
);

此外,我有一个函数返回此类型 fn_GetLinkedProject(整数)。 我需要做这样的事情:

SELECT 
    p.id, p.data, p.name, 
    pl.id linked_id, pl.name linked_name
FROM tb_projects p
   left join "fn_GetLinkedProject"(p.id) pl

我该怎么做?

P.S。 我看过this文章。

P.P.S。 我不想要以下方法:

SELECT
 p.id, p.data, p.name, 
    (select pl1.id from "fn_GetLinkedProject"(p.id) pl1 ) linked_id,
    (select pl2.name from "fn_GetLinkedProject"(p.id) pl2 ) linked_name
FROM tb_projects p

1 个答案:

答案 0 :(得分:7)

试试这个演示

CREATE TYPE dm_nameid AS (
  id int
, name text); -- simplified for demo

CREATE TABLE tb_projects(
  id   integer
, data text
, name text);

INSERT INTO tb_projects VALUES
  (1, 'data_1', 'name_1')
, (2, 'data_2', 'name_2')
, (3, 'data_3', 'name_3');

CREATE function fn_getlinkedproject(integer)
  RETURNS dm_nameid AS
$func$
   SELECT id, name FROM tb_projects
   WHERE  id = ($1 % 3) + 1;
$func$ LANGUAGE sql;

呼叫:

SELECT p.id AS p_id, p.data AS p_data, p.name AS p_name
     ,(fn_getlinkedproject(p.id)).*
FROM   tb_projects p;

更好在pg 9.3 +

中使用LATERAL联接
SELECT p.id AS p_id, p.data AS p_data, p.name AS p_name, f.*
FROM   tb_projects p
LEFT   JOIN LATERAL fn_getlinkedproject(p.id) f ON TRUE;

结果:

 p_id | p_data | p_name | id |  name
------+--------+--------+----+--------
    1 | data_1 | name_1 |  2 | name_2
    2 | data_2 | name_2 |  3 | name_3
    3 | data_3 | name_3 |  1 | name_1

如果您想重命名结果列,您必须:

SELECT p.id, p.data, p.name
     ,(fn_getlinkedproject(p.id)).id   AS linked_id
     ,(fn_getlinkedproject(p.id)).name AS linked_name
FROM   tb_projects p;

或者使用子查询来避免函数被调用两次(如果函数很昂贵):

SELECT p.id, p.data, p.name
    , (p.x).id AS linked_id, (p.x).name AS linked_name
FROM  (SELECT *, fn_getlinkedproject(id) AS x FROM tb_projects) p;

或者,在第9.3页+:

SELECT p.id AS p_id, p.data AS p_data, p.name AS p_name
     , f.id AS linked_id, f.name AS linked_name
FROM   tb_projects p
LEFT   JOIN LATERAL fn_getlinkedproject(p.id) f ON TRUE;

结果:

 id |  data  |  name  | linked_id | linked_name
----+--------+--------+-----------+-------------
  1 | data_1 | name_1 |         2 | name_2
  2 | data_2 | name_2 |         3 | name_3
  3 | data_3 | name_3 |         1 | name_1

使用PostgreSQL 8.4 - 9.3进行测试。可能也适用于8.2或8.3(未经测试) 请注意括号的位置!这些是必不可少的 阅读manual about composite types