如何在PostgreSQL函数中组合两个选择?

时间:2017-06-10 09:53:37

标签: postgresql

Union因为JSON列而爆炸,显然,临时表在PostgreSQL函数中几乎无用。

我来自MS SQL Server世界,似乎我在PostgreSQL中尝试的一切都是错误的。这就是我想要做的。有人可以告诉我最好的方法吗?或者以任何方式解决这个问题?

create or replace function getNextStories( previous_id bigint ) 
returns setof output_stories as
$$
    create temp table output_stories (
        "id"            bigint,
        submitted_date  timestamp with time zone,
        author          character varying,
        title           character varying,
        "content"       json,
        pinned          boolean
    );

    insert into output_stories("id", submitted_date, author, title, "content", pinned)
    select "id", submitted_date, categories, author, title, "content", pinned 
    from Story 
    where Pinned = true;

    insert into output_stories("id", submitted_date, author, title, "content", pinned)
    select "id", submitted_date, categories, author, "content", title, pinned 
    from Story 
    where Pinned = false
           and "id" < previous_id
    order by "id" desc
    limit 20;                     

    select * from output_stories
$$
language 'sql' ;

我尝试了很多不同的事情,每走一条路我都会遇到错误。这个特殊的尝试会返回这个。

ERROR:  type "output_stories" does not exist
********** Error **********

ERROR: type "output_stories" does not exist
SQL state: 42704

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的用例,您希望选择所有固定故事和(通过ID)前一个参考ID之后的20个非固定故事。除非我忽略了你问题中的某些内容,否则在我看来你根本不需要存储功能:

(
    SELECT id, title, body, pinned FROM Story 
    WHERE (id > 4 and not pinned) ORDER BY id DESC LIMIT 20
)
UNION ALL
SELECT id, title, body, pinned FROM Story WHERE pinned;

我用一堆测试做了an sqlfiddle。供参考:

-- minimal example table
CREATE TABLE story (
  id BIGINT PRIMARY KEY,
  title VARCHAR,
  body JSON,
  pinned BOOLEAN
)

-- minimal example records
INSERT INTO story (id, title, pinned) VALUES
(1, 'pinned', true),
(2, 'not pinned', false),
(4, 'previous id', false),
(5, 'next 1', false),      
(6, 'next 2', false),      
(7, 'next 3', true),       
(8, 'next 4', false);   

-- expectation
-- 1 INCLUDE (pinned)
-- 2 OMIT    (before ref ID)
-- 4 OMIT    (is ref ID)
-- 5 OMIT    (after ref ID, but outside limit 2)
-- 6 INCLUDE (after ref ID, not pinned)
-- 7 INCLUDE (pinned, but don't duplicate!)
-- 8 INCLUDE (after ref ID, not pinned)

-- Query
(
  SELECT id, title, body, pinned FROM Story 
  WHERE (id > 4 and not pinned) ORDER BY id DESC LIMIT 2
)
UNION ALL
  SELECT id, title, body, pinned FROM Story WHERE pinned;