从子表创建值数组

时间:2013-01-02 22:09:58

标签: sql arrays postgresql join plpgsql

例如,我有表users(id,name,email)。表photos(id,value) 有一个表userphotos由关系组成: user_id,photo_id。

我需要一个功能来以这种方式获取所有用户的照片:

  
      
  1. id1 name1 email1 photos1
  2.   
  3. id2 name2 email2 photos2
  4.   

用户的照片数量未知。

如何创建plpgsql函数来创建这样的结果?

CREATE OR REPLACE FUNCTION test_function()
  RETURNS TABLE(id int, name character varying, email character varying,  photos int[]) AS $
DECLARE
    u RECORD;
BEGIN
    FOR u IN SELECT * FROM users LOOP
        return NEXT u; -- will return user without photos
    -- but how to populate u with photos as array
    -- got from query:
    --          SELECT photo_id FROM userphotos WHERE user_id = u.id
    END LOOP;
END;
$ LANGUAGE plpgsql

PostgreSQL版本。 9.0。

1 个答案:

答案 0 :(得分:2)

可能看起来像这样:

CREATE OR REPLACE FUNCTION test_function()
  RETURNS TABLE(id int, name varchar, email varchar, photos int[]) AS
$func$
BEGIN

RETURN QUERY
SELECT u.id, u.name, u.email, array_agg(up.photo_id)  -- AS photo_ids
FROM   users u
LEFT   JOIN userphotos up ON  up.user_id = u.id
GROUP  BY u.int, u.name, u.email;

END
$func$ LANGUAGE plpgsql
  • 使用正确的引用。阅读有关dollar-quoting
  • 的手册
  • 使用RETURN QUERY作为从plpgsql函数返回行的最简单方法。不需要LOOP
  • LEFT JOIN包括完全没有照片的用户。
  • 注意命名冲突。 OUT子句中的所有RETURNS TABLE参数在所有地方都可见。

评论后的附录

如果您想加入多个 1:n表,则无法一次加入所有表。这就是发生的事情:
https://stackoverflow.com/a/12464135/939860

另一个与此问题的解决方案密切相关的答案:
https://stackoverflow.com/a/14110017/939860