Postgres IF控制结构选择

时间:2014-03-13 21:08:39

标签: sql postgresql plpgsql window-functions

这是场景。我想根据记录计数返回一个ntiled结果集。例如:

DO
$BODY$
IF ( SELECT count(*) < 50 FROM (
SELECT * FROM ( SELECT col1, col2, col3 FROM v_my_view) AS cnt; )
THEN
SELECT * FROM ( SELECT col1, col2, col3 FROM v_my_view ) AS qry;
ELSE (
SELECT *, NTILE(5) OVER (ORDER BY col1 DESC) AS my_tile FROM (
SELECT col1, col2, col3 FROM v_my_view ) AS tileme; )
END IF;
END;
$BODY$

请注意,语法是近似的,但意图应该是显而易见的。如果记录集很小,则返回查询,否则返回一个ntiled查询。我尝试执行此操作时遇到了各种错误消息,包括:

  

无法在非SETOF函数中使用RETURN QUERY

  

查询没有结果数据的目的地

另外,我知道您不应该在生产代码中使用*。

1 个答案:

答案 0 :(得分:0)

问题是您根本无法从DO语句返回行。您需要使用具有声明的RETURN类型的函数。要允许过程元素,请使用LANGUAGE plpgsql(这也是DO语句的默认值):

CREATE OR REPLACE FUNCTION foo()
  RETURNS TABLE(col1 text, col2 text, col3 text, my_tile int) AS
$func$
BEGIN

   IF (SELECT count(*) < 50 FROM v_my_view) THEN
      RETURN QUERY
      SELECT v.col1, v.col2, v.col3, 0 AS my_tile
      FROM   v_my_view v;
   ELSE
      RETURN QUERY
      SELECT v.col1, v.col2, v.col3, ntile(5) OVER (ORDER BY v.col1 DESC)
      FROM   v_my_view v;
   END IF;
END
$func$  LANGUAGE sql STABLE;

RETURNS子句中的数据类型必须与您的实际数据类型相匹配。查询中的列别名在结果中不可见,而是使用RETURNS子句中的声明名称。

此外,count(*)语法非常精细。

这可以用最后一列的简单查询和CASE语句替换,但是......