在用户定义的函数内将numeric转换为string

时间:2013-06-06 20:27:15

标签: sql postgresql types user-defined-functions plpgsql

我试图在用户定义的函数中调用/转换数字变量为字符串。我在考虑使用to_char,但它没有通过。

我的功能是这样的:

create or replace function ntile_loop(x numeric)
returns setof numeric as 
$$
  select

  max("billed") as _____(to_char($1,'99')||"%"???) from 
      (select "billed", "id","cm",ntile(100) 
      over (partition by "id","cm" order by "billed")
      as "percentile" from "table_all") where "percentile"=$1
      group by "id","cm","percentile";
$$
language sql;

我的目的是定义一个新变量“x%”作为其名称,x作为函数输入变化。在上下文中,x是数字,稍后将在函数中再次作为数字调用(此部分代码未包含在上面的示例中)。

我想要回归:

我只想返回一段代码,这样每次更改百分位数时,我都不必一次又一次地运行这段代码。我想计算5,10,20,30,...... 90百分位,并在每个id + cm组的同一个表中显示所有这些百分位数。

这就是我考虑宏观或功能的原因,但没有找到我喜欢的任何解决方案。

感谢您的回答。是的,在学习的过程中,我一定会阅读基础知识。今天是我使用SQL的第二天,但必须立即生成一些结果。

2 个答案:

答案 0 :(得分:2)

numeric转换为text是您遇到的最少问题。

  

我的目的是使用x定义一个新变量“x%”作为其名称   随函数输入而变化。

  • 首先: SQL函数中没有变量。 SQL函数只是有效SQL语句的包装器。输入和输出参数可以命名,但名称是静态,而不是动态。

  • 您可能会想到PL/pgSQL function,其中包含包含变量的过程元素。但是,参数名称仍然是静态。 plpgsql中没有动态变量名。您可以使用EXECUTE执行动态SQL,但这完全不同。

  • 虽然可以使用 名称 声明静态变量,例如"123%",但这种情况非常罕见这样做。也许是故意混淆代码?除此之外:不要。使用正确,简单,合法,小写的变量名称,无需双引号,也不会在输入错误后做出意想不到的事情。

  • 由于窗口函数ntile()返回integer并且您对结果进行了等式检查,因此输入参数应为 integer ,而不是numeric

  • assign a variable in plpgsql,您可以将赋值运算符:=用于单个变量,或SELECT INTO用于任意数量的变量。无论哪种方式,您希望查询返回单行,或者您需要loop

  • 如果您想要所选百分位数的最大billed,则不会GROUP BY x, y。这可能会返回多行而不会执行您想要的操作。使用不max(billed)的简单GROUP BY来获得一行。

  • 您无需双引号perfectly legal column names

有效的功能可能如下所示。这不是你想要做的,这是不可能的。但它可能会让你更接近你真正需要的东西。

CREATE OR REPLACE FUNCTION ntile_loop(x integer)
RETURNS SETOF numeric as 
$func$
DECLARE
   myvar text;
BEGIN

SELECT INTO myvar  max(billed)
FROM  (
   SELECT billed, id, cm
         ,ntile(100) OVER (PARTITION BY id, cm ORDER BY billed) AS tile
   FROM   table_all
   ) sub
WHERE  sub.tile = $1;

-- do something with myvar, depending on the value of $1 ...
END
$func$ LANGUAGE plpgsql;

长话短说,在尝试创建复杂功能之前,您需要学习基础知识

纯SQL

Q更新后:

  

我想计算5,10,20,30,...... 90%的百分位和显示   对于每个id + cm组,所有这些都在同一个表中。

这个简单的查询应该全部完成:

SELECT id, cm, tile, max(billed) AS max_billed
FROM  (
   SELECT billed, id, cm
         ,ntile(100) OVER (PARTITION BY id, cm ORDER BY billed) AS tile
   FROM   table_all
   ) sub
WHERE (tile%10 = 0 OR tile = 5)
AND    tile <= 90
GROUP  BY 1,2,3
ORDER  BY 1,2,3;

% .. modulo operator
GROUP BY 1,2,3 .. positional parameter

答案 1 :(得分:0)